Read one2many field in inherited model - python

In odoo v13, the crm.lead model is inherited and modified by the sale_crm module.
In the sale_crm module, the model crm.lead is inherited and a one2many field is added, order_ids. This is an array of sales orders associated with the lead.
I am trying to inherit the crm.lead model, and create a new field that is computed using the order_ids field.
I added sale_crm in the manifest dependencies
I inherit the crm.lead model and attempt to concat the names of all the associated SOs:
class Co7Lead(models.Model):
_inherit = "crm.lead"
so_list = fields.Text(
compute='_get_sos_text',
string="Text list of associated SOs",
help="A comma separated list of SOs associated with this lead")
def _get_sos_text(self):
txt = ""
for order in super(Co7Lead, self).order_ids:
txt += order.name + ""
return txt
Unfortunately, this causes a stack overflow (haha!)
I believe I need to use .browse on the order_ids field but I'm not able to find any examples on how to do this.

The compute method must assign the computed value to the field. If it uses the values of other fields (order_ids.name), it should specify those fields using depends().
You don't need to use super here, self is a record set, so loop over it to access the value of order_ids for each record.
Example:
#api.depends('order_ids.name')
def _get_sos_text(self):
for lead in self:
lead.so_list = "\n".join(order.name for order in lead.order_ids)

Related

Python / Django: Make a lookup / database query inside a model class

What is the right way to lookup a table and use its last value as a value in a new model instance? Something like this:
class MyClass(models.Model):
id = models.AutoField(primary_key=True)
obj = MyClass.objects.latest('id')
my_field = models.IntegerField(default=(obj+1))
I need a db column, which keeps track of the primary_key, but is independent of it and can also be modified. Also I need to use its value as default when creating new instances of the Model.
you can use custom constructor as described in the docs:
https://docs.djangoproject.com/en/2.2/ref/models/instances/
you will need to define the obj field either as integer(to store the id of the previous record) or as a foreign key(if you want to reference the previous db record). In the second case you will need to pass the name of the model to the ForeignKeyField constructor as string('MyClass') and not directly(MyClass).

related field from inherited model in odoo

i have a model that inherits res.partner model
class supplierDetails(models.Model):
_inherit = 'res.partner'
farmer_code = fields.Char(string="Farmer's Code")
Now i want the values from farmer_code in another model, so as per this answer, i reached this far.
class productTest(models.Model):
_name = 'quality.physical'
_inherit = 'res.partner'
frm_code_ids = fields.Many2one('res.partner',string="Farmer Code")
frm_cod = fields.Char(related='frm_code_ids.farmer_code',store=True,readonly=True)
Now i am getting KeyError: 'farmer_code'. What do i do to fix this? Thanks in advance.
Your code should work, repeat the process step by step make sure the res.partner have this field you may forget to put the class in the __init__.py file.
# related field without store is like a compute field it's computed on fly
related_field_name = fields.FieldType(related='your_m2o.target_field_name')
If you put store=True it will be added to the database and recomputed whenever you change the value of many2one.
You can go more than one level ex: your_m2m.another_m2o_field.target_field_name.
Field type should be the same as the target field.
Just make sure the target model have that field.

Odoo delegation inheritance delete corresponding records of inherited class

I've extended a default class using _inherits. I am using Odoo v9.
class new_product_uom(models.Model):
_inherits = {'product.uom':'uomid', }
_name = "newproduct.uom"
uomid = fields.Many2one('product.uom',ondelete='cascade', required=True).
#declare variables and functions specific to new_product_uom
sellable = fields.Boolean('Sell products using this UoM?', default=True)
[...]
If I delete the corresponding record in product.uom, the new_product_uom is deleted.
If I were to delete a new_product_uom record, nothing happens to the corresponding product_uom record.
I'd like for BOTH records to be automatically deleted when either is deleted. Is there a way I can do this? Thanks in advance for the help.
Clarification:
product.uom is a default odoo class. It holds UoM records (inches, centimeters, etc). I use delegation inheritance to extend this class. See:
https://www.odoo.com/documentation/9.0/howtos/backend.html#model-inheritance
So, when I add a record for newproduct.uom, a record is automatically created under the model product.uom. I can assign the values of the corresponding record in product.uom by addressing them in newproduct.uom.
For my uses, it will be intended as a Parent->child relation, with newproduct.uom being the parent, and the default product.uom being the child. I chose this method of inheritance to allow quicker creation and modification of related values, as well as a separation of functions (rather than overriding the default methods for default operations).
In your parent class override unlink. Not sure if I have the correct class name. Delete the child record and then delete the current record.
#api.multi
def unlink(self):
self.uom_id.unlink()
return super(new_product_uom, self).unlink()

How to query MongoEngine documents with inheritance?

I've been using a Node MongoEngine document for a while.
I am trying to go from a simpe Node model to some more specific elements inheriting from it.
What I've done so far
At first, I was not aware of the inheritance possibility offered by MongoEngine (see here), so I was using a 'label' field to distinguish between 3 types of Nodes (respectively Keyword, Url and Domain).
Here is the original model:
class Node(Document):
project = ReferenceField(Project,
reverse_delete_rule=CASCADE,
required=True,)
name = StringField(required=True, unique_with=['project', 'label'])
label = StringField(required=True)
volume = IntField()
clusters = ListField(ReferenceField(Cluster, reverse_delete_rule=PULL))
x = FloatField(default=random.random())
y = FloatField(default=random.random())
connections = IntField(default=0)
meta = {
'indexes': ['project', 'label', 'name', 'clusters'],
}
I worked for some time with this model, so the node collection is currently populated with thousands of documents.
Then I implemented inheritance by adding 'allow_inheritance': True to the model and creating the following model:
Inherited model
class Keyword(Node):
""" A MongoEngine Document for keyword management. """
a_keywor_specific field = IntField()
def foo(self):
print('this is a keyword specific method')
Now this works fine for creating and saving new Keyword documents.
The thing I'm having trouble with is querying the old Nodes added before this change.
Question
If I try to query all the existing nodes, only the one I added after the inheritance change is returned:
In [21]: Node.objects()
Out[21]: [<Keyword: Keyword object>]
How can I access all the Nodes that were added before introducing inheritance ?
Is there any way to migrate those old Nodes to Keywords, Urls and Domains based on their original label attribute ?
Thanks !
This happened because when you created an inherited model, the old model queries use _cls attribute to query this model's records. But old records don't have this field.
Fill in this attribute to old records.
As for you second question.
I think, if you are going to make a migration script that will fill _cls field, you can fill its value depending on the value of label field.
You can find the required _cls values inserting records of each model.

How to create user defined fields in Django

Ok, I am working on a Django application with several different models, namely Accounts, Contacts, etc, each with a different set of fields. I need to be able to allow each of my users to define their own fields in addition to the existing fields. I have seen several different ways to implement this, from having a large number of CustomFields and just mapping a custom name to each field used by each user. I have also seem recommendations for implementing complex mapping or XML/JSON style storage/retrieval of user defined fields.
So my question is this, has anyone implemented user defined fields in a Django application? If so, how did you do it and what was your experience with the overall implementation (stability, performance, etc)?
Update: My goal is to allow each of my users to create n number of each record type (accounts, contacts, etc) and associate user defined data with each record. So for example, one of my users might want to associate an SSN with each of his contacts, so I would need to store that additional field for each Contact record he creates.
Thanks!
Mark
What if you were to use a ForeignKey?
This code (untested and for demo) is assuming there is a system-wide set of custom fields. To make it user-specific, you'd add a "user = models.ForiegnKey(User)" onto the class CustomField.
class Account(models.Model):
name = models.CharField(max_length=75)
# ...
def get_custom_fields(self):
return CustomField.objects.filter(content_type=ContentType.objects.get_for_model(Account))
custom_fields = property(get_fields)
class CustomField(models.Model):
"""
A field abstract -- it describe what the field is. There are one of these
for each custom field the user configures.
"""
name = models.CharField(max_length=75)
content_type = models.ForeignKey(ContentType)
class CustomFieldValueManager(models.Manager):
get_value_for_model_instance(self, model):
content_type = ContentType.objects.get_for_model(model)
return self.filter(model__content_type=content_type, model__object_id=model.pk)
class CustomFieldValue(models.Model):
"""
A field instance -- contains the actual data. There are many of these, for
each value that corresponds to a CustomField for a given model.
"""
field = models.ForeignKey(CustomField, related_name='instance')
value = models.CharField(max_length=255)
model = models.GenericForeignKey()
objects = CustomFieldValueManager()
# If you wanted to enumerate the custom fields and their values, it would look
# look like so:
account = Account.objects.get(pk=1)
for field in account.custom_fields:
print field.name, field.instance.objects.get_value_for_model_instance(account)

Categories

Resources