Twisted adbapi fetchone - twisted

If I use runInteraction of Twisted's adbapi, and within the function that I call I do something like
curs. execute("SELECT id FROM mytable WHERE name='bob'")
id = curs.fetchone()[0]
Am I guaranteed the id from this select or could it be from one of the other deferred threads?

Deferreds are thread-safe so you can get guarantee.
Example code lookslike:
def _getAge(txn, user):
# this will run in a thread, we can use blocking calls
txn.execute("SELECT * FROM foo")
# ... other cursor commands called on txn ...
txn.execute("SELECT age FROM users WHERE name = ?", user)
result = txn.fetchall()
if result:
return result[0][0]
else:
return None
def getAge(user):
return dbpool.runInteraction(_getAge, user)
def printResult(age):
if age != None:
print age, "years old"
else:
print "No such user"
getAge("joe").addCallback(printResult)
This from official docs. I didn't remove any row to more clear and teaching.

Related

My aiogram code is passing a list of tuples do database (i guess) instead of whole expressions

import logging
import sqlite3
from aiogram import Bot, Dispatcher, executor, types
API_TOKEN = "6178046203:AAEAdOfU9k1jOrhMCI-E_YNG4DOaHF_uHrQ"
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
con = sqlite3.connect("database1")
cur = con.cursor()
cur.execute("""
CREATE TABLE IF NOT EXISTS notes(
note_id INTEGER PRIMARY KEY AUTOINCREMENT,
notetext TEXT)""")
con.commit()
#dp.message_handler(commands="database1")
async def show_database(message: types.Message):
cur.execute("""
SELECT notetext
FROM notes
LIMIT 12
""")
db_show = cur.fetchall()
con.commit()
await message.answer(text=db_show)
#dp.message_handler(content_types="text")
async def text_parse_to_sql(message: types.Message):
await message.answer(text="Message got!")
if "add to database" in message.text:
db_insert = message.text
cur.executemany("INSERT INTO notes VALUES(NULL, ?)", db_insert)
con.commit()
await message.answer(text="Added to database!")
if __name__ == '__main__':
executor.start_polling(dp)
So, as you can see on the image, i am getting a list of tuples from the database, when i wanted to get a whole expression like "jama jama add to database" instead. Why do i get this strange tuple list, help please!? How can i get the whole expressions? The whole code of this bot is down here.

Understanding Full Join in Django

I have two models in my app:
# Create your models here.
class Melody(models.Model):
notes = models.JSONField()
bpm = models.IntegerField()
aimodel = models.CharField(max_length=200)
score = models.IntegerField(default=0)
person = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="melodies")
date_created = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.id)
class Vote(models.Model):
user_score = models.IntegerField(validators=[MaxValueValidator(1), MinValueValidator(-1)])
melody = models.ForeignKey(Melody, on_delete=models.CASCADE, related_name="scores")
person = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="voters")
def __str__(self):
return f"{self.person} - {self.melody} - {self.score}"
And I get the melodies of the current user by
# Get melodies of current user
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
I would like to add to this results the vote of the user to each melody, if there is one, otherwise just null so I can loop over the melodies and retrieve the values:
melody.notes = ...
melody.bpm = ...
melody.user_score = This is the values I do not know still how to get, Null if user has not voted
I was reading about select_related but when I use it it always says
"Invalid field name(s) given in select_related: 'xxxx'. Choices are: (none)"
What am I missing?
EDIT
I solved it based on the answer of #Fnechz by making two queries and then looping over the elements so I can add the user_score to the melody:
# Get melodies of current user
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
# Get votes of the user
votes = Vote.objects.all().filter(person=person)
for i, m_melody in enumerate(melodies):
for m_vote in votes:
if (m_vote.melody.id == m_melody['id']):
melodies[i]['user_score'] = m_vote.user_score
return JsonResponse({"melodies": list(melodies)})
Not sure if this is the best way to achieved it
I do not know if there is a direct method to accomplish what you want with a single query. But I guess concatenating the queryset results might work.
from itertools import chain
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
votes = #query your vote model here to get the user_score
result_list = list(chain(melodies,votes))
If I have understood your question that might work

Airflow: Best way to pass BigQuery result as XCom [duplicate]

I'm using Airflow 1.8.1 and I want to push the result of a sql request from PostgreOperator.
Here's my tasks:
check_task = PostgresOperator(
task_id='check_task',
postgres_conn_id='conx',
sql="check_task.sql",
xcom_push=True,
dag=dag)
def py_is_first_execution(**kwargs):
value = kwargs['ti'].xcom_pull(task_ids='check_task')
print 'count ----> ', value
if value == 0:
return 'next_task'
else:
return 'end-flow'
check_branch = BranchPythonOperator(
task_id='is-first-execution',
python_callable=py_is_first_execution,
provide_context=True,
dag=dag)
and here is my sql script:
select count(1) from table
when i check the xcom value from check_task it retrieves none value.
If i'm correct, airflow automatically pushes to xcom when a query returns a value. However, when you look at the code of the postgresoperator you see that it has an execute method that calls the run method of the PostgresHook (extension of dbapi_hook). Both methods do not return anything, as such it pushes nothing to xcom.
What we did to fix this is create a CustomPostgresSelectOperator, a copy of the PostgresOperator, but instead of 'hook.run(..)' do 'return hook.get_records(..)'.
Hope that helps you.
Finally, I created a new Sensor ExecuteSqlOperator in the plugin manager under $AIRFLOW_HOME/plugins.
I used CheckOperator as an example and I modified the returned value: the basic running of this operator was exactly the reverse of what I needed.
Here's the of the default ExecuteSqlOperator:
CheckOperator
and here is my customized SqlSensor: ReverseSqlSensor
class SqlExecuteOperator(BaseOperator):
"""
Performs checks against a db. The ``CheckOperator`` expects
a sql query that will return a single row.
Note that this is an abstract class and get_db_hook
needs to be defined. Whereas a get_db_hook is hook that gets a
single record from an external source.
:param sql: the sql to be executed
:type sql: string
"""
template_fields = ('sql',)
template_ext = ('.hql', '.sql',)
ui_color = '#fff7e6'
#apply_defaults
def __init__(
self, sql,
conn_id=None,
*args, **kwargs):
super(SqlExecuteOperator, self).__init__(*args, **kwargs)
self.conn_id = conn_id
self.sql = sql
def execute(self, context=None):
logging.info('Executing SQL statement: ' + self.sql)
records = self.get_db_hook().get_first(self.sql)
logging.info("Record: " + str(records))
records_int = int(records[0])
print (records_int)
return records_int
def get_db_hook(self):
return BaseHook.get_hook(conn_id=self.conn_id)

Odoo 10 selection fields value

How can i get selection fields value in odoo 10?
def compute_default_value(self):
return self.get_value("field")
I tried this,
def compute_default_value(self):
return dict(self._fields['field'].selection).get(self.type)
Also tried this,but it is not working.
Please help me, i could not find the solution.
Thank you.
You can do this in a following manner:
self._fields['your_field']._desription_selection(self.env)
This will return the selection list of pairs (value, label).
If you just need possible values, you can use get_values method.
self._fields['your_field'].get_values(self.env)
But it's not a common way. Most of the time people define selections differently and then use those definitions. For example, I commonly use classes for those.
class BaseSelectionType(object):
""" Base abstract class """
values = None
#classmethod
def get_selection(cls):
return [(x, cls.values[x]) for x in sorted(cls.values)]
#classmethod
def get_value(cls, _id):
return cls.values.get(_id, False)
class StateType(BaseSelectionType):
""" Your selection """
NEW = 1
IN_PROGRESS = 2
FINISHED = 3
values = {
NEW: 'New',
IN_PROGRESS: 'In Progress',
FINISHED: 'Finished'
}
You can use this class wherever you want, just import it.
state = fields.Selection(StateType.get_selection(), 'State')
And it's really handy to use those in the code. For example, if you want to do something on a specific state:
if self.state == StateType.NEW:
# do your code ...
I don't get the question fully, but let me try to answer. Why not just define the selection as method and use it for both situations:
from datetime import datetime
from odoo import models, fields
class MyModel(models.Model):
_name = 'my.model'
def month_selection(self):
return [(1, 'Month1'), (2, 'Month2')]
def compute_default_value(self):
selection = self.month_selection()
# do whatever you want here
month = fields.Selection(
selection=month_selection, string='Month',
default=datetime.now().month, required=True)

How to standardize field values on create or write in Odoo 8?

In Odoo 8, is there a preferred method for standardizing field values on create or write? Several methods come to mind, but this functionality seems like it belongs in the API. Essentially, I am wanting to create a field that specifies a standardize function, somewhat like a compute field that only specifies an inverse function. Does this already exist somewhere in the API?
Method 0: Create a field that specifies a standardize function.
The only flaw that I can see with this method is that the API does not exist.
import openerp
class Model(openerp.models.Model):
_name = 'addon.model'
field = openerp.fields.Text(
required=True,
standardize='_standardize_field',
)
#openerp.api.one
def _standardize_field(self):
self.field = self.field.upper()
Method 1: Override the create and write methods to insert a call to standardize the field.
This works, but seems rather verbose for what could be done with a single function, above. Note that the constraint is required if required=True and the standardization might yield an empty field.
import openerp
class Model(openerp.models.Model):
_name = 'addon.model'
field = openerp.fields.Text(
required=True,
)
#openerp.api.one
#openerp.api.constrains('field')
def _constrains_field(self):
if len(self.field) == 0:
raise openerp.exceptions.ValidationError('Field must be valid.')
def _standardize(self, args):
if 'field' in args:
# Return standardized field or empty string.
args['field'] = args['field'].upper()
#openerp.api.model
def create(self, args):
self._standardize(args)
return super(Model, self).create(args)
#openerp.api.multi
def write(self, args):
self._standardize(args)
super(Model, self).write(args)
return True
Method 2: Use a computed field and a bit of magic.
This works but feels a bit contrived. In addition, this method requires that the standardization function is deterministic, or this may create an infinite loop. Note that the standardization function may be called twice, which could be a concern if standardization is an expensive operation.
import openerp
class Model(openerp.models.Model):
_name = 'addon.model'
field = openerp.fields.Text(
compute=lambda x: x,
inverse='_inverse_field',
required=True,
store=True,
)
#openerp.api.one
#openerp.api.constrains('field')
def _constrains_field(self):
if self._standardize_field() is None:
raise openerp.exceptions.ValidationError('Field must be valid.')
def _inverse_field(self):
field = self._standardize_field()
# If the field is updated during standardization, this function will
# run a second time, so use this check to prevent an infinite loop.
if self.field != field:
self.field = field
def _standardize_field(self):
# Return the standardized field.
return self.field.upper()
Method 3: Use a regular field and a computed field, with only the computed field being exposed in the view.
The readonly flag and the constraints help to protect the underlying field, but I am not certain that this method would maintain data integrity, and the method as a whole feels contrived.
import openerp
class Model(openerp.models.Model):
_name = 'addon.model'
field = openerp.fields.Text(
readonly=True,
required=True,
)
field_for_view = openerp.fields.Text(
compute='_compute_field_for_view',
inverse='_inverse_field_for_view',
required=True,
)
#openerp.api.one
#openerp.api.depends('field')
def _compute_field_for_view(self):
self.field_for_view = self.field
#openerp.api.one
#openerp.api.constrains('field', 'field_for_view')
def _constrains_field(self):
if self._standardize_field() is None:
raise openerp.exceptions.ValidationError('Field must be valid.')
def _inverse_field(self):
self.field = self._standardize_field()
def _standardize_field(self):
# Return the standardized field.
return self.field_for_view.upper()
Maybe the 'default' attribute is an implementation of your approach #1?
Here's the example taken from the Odoo8 documentation at https://www.odoo.com/documentation/8.0/reference/orm.html#creating-models
a_field = fields.Char(default=compute_default_value)
def compute_default_value(self):
return self.get_value()
Another option is to override the write() method in your subclass to add your call like so:
def write(self, vals):
for record in self:
# do the cleanup here for each record, storing the result in
# vals again
# call the super:
res = super(extendedProject, self).write(vals)
return res
vals is a dictionary with the modified values to store; self is a recordset with all records to store the values to. Note that the transaction in Odoo may still be rolled back after returning from your call to write.