Python property in hybrid_method - flask-sqlalchemy

I am trying to calculating the age of an object instance by using the attribute "year".
class User(db.Model):
__tablename__ = 'user'
__table_args__ = {'schema': 'data'}
id = db.Column(db.Integer, primary_key=True, server_default=db.FetchedValue())
birthday = db.Column(db.Date)
#hybrid_method
def age(self):
return datetime.datetime.now().year - self.birthday.year
While
test = User.query.first()
test.year
is returning 20 (correct), the following query is returning an error
test = User.query.filter(User.age==20).all()
AttributeError: Neither 'InstrumentedAttribute' object nor
'Comparator' object associated with User.birthday has an attribute
'year'
How can I get the attribute parsed?
EDIT based on comment:
Solution 1:
#hybrid_property
def age(self):
return datetime.datetime.today().year - self.birthday.year
#age.expression
def age(cls):
return datetime.datetime.today().year - func.year(cls.birthday)
Solution 2 based on SQLAlchemy - Querying with DateTime columns to filter by month/day/year:
#hybrid_property
def age(self):
return datetime.datetime.today().year - self.birthday.year
#age.expression
def age(cls):
return datetime.datetime.today().year - extract('year', cls.birthday)

Related

Update records on one2many fields in wizard for odoo16

Geting Issue 'TypeError: unhashable type: 'dict' for insert values in one2many field from onchange method in odoo16
My code is below:
class EmployeeAddWizard(models.TransientModel):
_name = 'employee.add.wizard'
line_ids = fields.One2many('employee.goal.add.line', 'wizard_id', string="Lines")
#api.onchange('challenge_id', 'employee_id')
def _onchange_action_goal_add(self):
r = []
value = {}
self.line_ids = {}
if self.challenge_id and self.employee_id:
goal_records = self.env['gamification.challenge.line'].search([('challenge_id', '=', self.challenge_id.id)])
for emp in self.employee_id:
for line in goal_records:
data = {'wizard_id': self.id, # Other table m2o
'goal_definition_id': line.definition_id.id,
'goal_rating': 0.0,
'goal_target': line.target_goal,
'employee_id': emp.id,
}
r.append(data)
value.update(records=r)
self.line_ids = value['records']
class GoalLine(models.Model):
_name = 'employee.goal.add.line'
wizard_id = fields.Integer()
goal_definition_id = fields.Many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade")
goal_rating = fields.Float('Rating', required=True)
goal_target = fields.Float('Target Value ', required=True)
employee_id = fields.Many2one('res.users', string="Employee", required=True, ondelete="cascade")
Thanks in advance
You passed a list of dicts which is not valid, you need to use special commands
Example:
r.append(Command.create(data))
or:
r.append((0, 0, data))
You can use Command.clear(), to remove previous lines if needed ( self.line_ids = {} should raise an error: ValueError: Wrong value).
Check this answer

Django restframework SerializerMethodField background work

I am writing a project in Django with rest framework by using SerializerMethodField. This method makes queries for every row to get data, or View collects all queries and send it to DB? Django can make it as one joint query?
class SubjectSerializer(serializers.ModelSerializer):
edu_plan = serializers.SerializerMethodField(read_only=True)
academic_year_semestr = serializers.SerializerMethodField(read_only=True)
edu_form = serializers.SerializerMethodField(read_only=True)
def get_edu_plan(self, cse):
return cse.curriculum_subject.curriculum.edu_plan.name
def get_academic_year_semestr(self, cse):
semester = cse.curriculum_subject.curriculum.semester
return {'academic_year': semester.academic_year, 'semester': semester}
def get_edu_form(self, cse):
return cse.curriculum_subject.curriculum.edu_form.name
class Meta:
model = CurriculumSubjectEmployee
fields = [
'id',
'name',
'edu_plan',
'academic_year_semestr',
'edu_form'
]
class SubjectViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = SubjectSerializer
def get_queryset(self):
contract = self.request.user.employee.contract
if contract is None:
raise NotFound(detail="Contract not found", code=404)
department = contract.department
cses = CurriculumSubjectEmployee\
.objects\
.filter(curriculum_subject__department=department)
return cses

How to track One2many field in Odoo12?

I am trying to log the changes on a One2many field using track_visibility='onchange'. But it's not working.
Here is the code:
respartner.py
bank_account_ids = fields.One2many('customer.bank.account','partner_id',
string='Account',track_visibility="onchange")
account.py
_name = 'customer.bank.account'
_description = 'Partner Bank Account Details'
partner_id = fields.Many2one('res.partner',string="Partner")
name = fields.Integer(string="Account Number",required=True,
track_visibility="onchange")
bank_id = fields.Many2one('partner.bank',string="Bank",track_visibility="onchange")
branch_id = fields.Many2one('partner.bank.branch',string="Branch",
track_visibility="onchange")
Yes, No need to touch ORM. Try this
class ParentClass(models.Model):
_name = 'parent.class'
_inherit = ['mail.thread']
child_ids = fields.One2many('child.class', 'relational_field_name_id')
class ChildClass(models.Model):
_name = 'child.class'
_inherit = ['mail.thread']
name = fields.Char(tracking=True) # Note that tracking is true here
relational_field_name_id = fields.Many2one('parent.class')
def write(self, vals):
super().write(vals)
if set(vals) & set(self._get_tracked_fields()):
self._track_changes(self.relational_field_name_id)
def _track_changes(self, field_to_track):
if self.message_ids:
message_id = field_to_track.message_post(body=f'<strong>{ self._description }:</strong> { self.display_name }').id
trackings = self.env['mail.tracking.value'].sudo().search([('mail_message_id', '=', self.message_ids[0].id)])
for tracking in trackings:
tracking.copy({'mail_message_id': message_id})
If you just want to track on relational and not current model then use write instead of copy method
tracking.write({'mail_message_id': message_id})
And for delete and create you can just use message_post inside create and unlink method
self.message_post(body=f'<strong>{ self._description }:</strong> { self.display_name } created/deleted')

SQL Query logic to Django ORM Query logic

I have tried to think about how the following SQL query would be structured as a Django ORM query but I have had no luck in my multiple attempts. Can anyone help?
SELECT targets_genetarget.gene, count(targets_targetprediction.gene) as total
FROM targets_genetarget
LEFT OUTER JOIN targets_targetprediction on targets_targetprediction.gene =
targets_genetarget.gene
WHERE list_name LIKE %s
GROUP BY targets_genetarget.gene
class GeneTarget(models.Model):
list_name = models.CharField(max_length=100)
gene = models.CharField(max_length=50)
date_added = models.DateField(auto_now=True)
class Meta:
unique_together = (('list_name', 'gene'),)
def __str__(self):
return self.list_name
class TargetPrediction(models.Model):
specimen_id = models.CharField(max_length=100)
patient_peptide = models.ForeignKey(Peptide, on_delete=models.CASCADE, verbose_name="Peptide", related_name="predictions")
allele = models.ForeignKey(Allele, on_delete=models.CASCADE, verbose_name="Allele", related_name="predictions")
gene = models.CharField(max_length=50)
class Meta:
unique_together = (('specimen_id', 'patient_peptide', 'allele', 'gene'),)
def get_absolute_url(self):
return f'/samples/specid-{self.specimen_id}'
def __str__(self):
return (f'Specimen: {self.specimen_id} Peptide: {self.patient_peptide} Allele: {self.allele} Gene: {self.gene} ')
There's nothing stopping you declaring the TargetPrediction.gene field as a foreign key using the to_field attribute, so you wouldn't need to change the data at all:
class TargetPrediction(models.Model):
...
gene = models.ForeignKey("GeneTarget", to_field="gene")
Now your query simply becomes:
GeneTarget.objects.filter(list_name="whatever").values("gene").annotate(total=Count("targetprediction"))

How to filter a many2many field in odoo8?

I've the following model, and the extend to the product_template
class Version(models.Model):
_name='product_cars_application.version'
name = fields.Char()
model_id = fields.Many2one('product_cars_application.model',string="Model")
brand_id = fields.Char(related='model_id.brand_id.name',store=True,readonly=1)
year_id = fields.Char(related='model_id.year_id.name',store=True,readonly=1)
from openerp.osv import osv,fields as Fields
class product_template(osv.osv):
_name = 'product.template'
_inherit = _name
_columns = {
'versions_ids':Fields.many2many('product_cars_application.version',string='Versions')
}
And the following controller which I need to filter products by version_id
#http.route('/pa/get_products/<version_id>', auth='none', type='json',website=True)
def get_products(self,version_id,**kwargs):
#TODO APPEND SECURITY
version_id = int(version_id)
products = http.request.env['product.template'].sudo().search([(version_id,'in','versions_ids')])
I get none products in return while the version_id is in versions_ids.
Do anyone knows what I'm doing wrong?
I need to make the value of comparison of the field a list, maybe becouse the field versions_ids is a many2many
I have solved like this:
#http.route('/pa/get_products/<version_id>', auth='none', type='json',website=True)
def get_products(self,version_id,**kwargs):
#TODO APPEND SECURITY
products = http.request.env['product.template'].sudo().search([('versions_ids','in',[version_id])])
list = []
for p in products:
list.append([p.id, p.name])
return {
'products':list,
}
"return products.ids" is missing inside get_products like:
#http.route('/pa/get_products/<version_id>', auth='none', type='json',website=True)
def get_products(self,version_id,**kwargs):
#TODO APPEND SECURITY
version_id = int(version_id)
products = http.request.env['product.template'].sudo().search([(version_id,'in','versions_ids')])
return products.ids