Odoo 10 - Counting values of linked records - python

In Odoo 10 I have created my own custom application (using the new studio feature), however I have run into an issue trying to compute data between records that belong to different views.
In the scenario I have two models (model A and model B), where records from model B are connect to records from model A via a many2one relational field. There is a field in Model B that counts a numerical value entered into it.
Ideally what I would like to achieve is have some form of Automated Action / Server Action, that loops through the records in Model A, then loops through related records in Model B adding together the values of the previously mentioned numerical value field and sets the value of a field in model A equal to the equated number, before continuing onto the next record.
For example sake say the field names are:
Model A = x_a
- Model A ID Field = x_id_field
- Target field for computed value = x_compute
Model B = x_b
- many2one field = x_a_id
- numerical field = x_value_field
I have attempted to use the automated actions to execute some basic Python code (because I thought this would be as simple as a nested loop) however all my attempts have been failures due to not being familiar with how to loop through records in odoo and how to access other models and their records (from python).
How would I go about accomplishing this?

Ideally what I would like to achieve is have some form of Automated
Action / Server Action, that loops through the records in Model A,
then loops through related records in Model B adding together the
values of the previously mentioned numerical value field and sets the
value of a field in model A equal to the equated number, before
continuing onto the next record.
Create an Automated Action with Related Document Model = model a
On the Actions tab create a Server Action:
model_b_records = self.env['model_b'].search([('many2one_field', '!=', False)])
for record in model_b_records:
record.many2one_field.target_field_for_computed_value = record.numerical_field
Save the Server Action and execute it.
The code should be self-explanatory, for any questions do not hesitate to ask and comment below.

Related

How to keep assigned attributes to a queryset object after filtering? Alternatives?

Maybe it's a stange answer, so i will explain why i'm doing this.
I have a model of Products. I have to assign each of them some stock.
So i have a function on the Products model that calculates a lot of neccesary things like stock and returns a QuerySet.
Since my db model is a little bit "complicated" i can't use annotations in this case. So i decided to execute this database query manually and then, assign each product on the querySet a stock attribute manually. Something like:
for product in queryset_products:
product.stock = some_stock_calc...
The problem comes when i want to use filters this queryset_product.
after executing something like:
queryset_products = queryset_products.filter(...)
the stock attribute gets lost
Any solution?
Since you can't use annotate(), if you can add a separate column to store stock in your Product table, you can make a the filter queries any time.
Maybe have a celery task that does all the calculations for each Product and save to new column.
Otherwise, without annotate you can't have the stock attribute in the queryset.
It can be solved differently, you can run one loop as
queryset_products = list(queryset_products.filter(...))
for product in queryset_products:
setattr(product, "stock") = some_stock_calc...
Basically, you need to fetch all the records from the database as query being lazy it will be lost since it will be re-evaluated unless results have been cached/stored.
All operations on the queryset like .filter() are symbolic until the queryset is enumerated. Then an SQL query is compiled and executed. It is not effective to calculate the stock on a big unfiltered queryset and then even to run it again filtered. You can split the filter to conditions unrelated to stock appended to the queryset and then a filter related to stock that you evaluate in the same Python loop where you calculate the stock.
result = []
for product in queryset_products.filter(**simple filters):
product.stock = some_stock_calc...
if product.stock > 0 or not required_on_stock:
result append(product)
A cache field of possible active products that could be on stock is very useful for the first simple filter.
Maybe the stock calculation is not more complicated then e.g. a stock at midnight plus a sum of stock operations since midnight. Then the current stock can be calculated by a Subquery in an annotation and filtered together. It will by compiled to one SQL with a main query with joins to your related models and a relative simple subquery for stock. (That would be another question.)

Django Automatically Standardize Model Field

I am trying to create a model field for US States that can be used across multiple models in my app. I have a dictionary of common state abbreviations and spellings matched to a standardized set of names - e.g.
state_dict = {"WV": "West Virginia", "W Virginia": "West Virginia", "WY": "Wyoming"}
I'd like the model field to automatically look up its value against the dictionary and set the field's value to the standardized name if a match is found. If no match is found, the field should raise an exception of some sort.
Things I've Tried
Choice Field- This doesn't work for my use case, as the models are only modified through a REST API. Furthermore the API receives data from 3p sources, so enforcing the standardization client-side isn't an option.
Django-Localflavor US - I've tried to use the custom state field provided by this package, but it just implements a choice field that doesn't automatically standardize the data.
First of all, I'd save the canonical value in one model and the possible variations in another model in which a foreign key points to the canonical value.
During form validation (or if the data are acquired differently, then maybe in pre_save), you could look up the input value in the variations model; if found, change the value to the canonical one, if not found, raise an error.

How to get all objects, excluding ones that have records with same related field id value

Model Model1 has ForeignKey field (my_field) to Model2. I want to retrieve all Model1 without records that already have at least 1 record with same my_field value.
I think you need to get all distinct records from Model1, So this is how you can do it in django.
Model1.objects.all().distinct()
Hope this would answer your question.
Thanks

Django adding data to models from another class

I have too models speakerCabinet and speakerElement. speakerCabinet has many-to-many relation to speakerElement.
I need to do some calculations on ideal speaker cabinet size that are using some of the speakerElement variables. I would like to contain these calculations to separate class because they are also used without the model.
Then comes the tricky part. My view gets the speakerCabinet instance and generates the speaker element info with:
{% for cab in speakerCabinet.SpeakerElement.all %}
Is there any simple way add that calculation data to my speaker element model?

Applying machine learning to recommend items from an existing database

I've got an existing database full of objects (I'll use books as an example). When users login to a website I'd like to recommend books to them.
I can recommend books based on other people they follow etc but I'd like to be more accurate so I've collected a set of training data for each user.
The data is collected by repeatedly presenting each user with a book and asking them if they like the look of it or not.
The training data is stored in mongodb, the books are stored in a postgres database.
I've written code to predict wether or not a given user will like a given book based on their training data, but my question is this:
How should I apply the data / probability to query books in the postgres database?
Saving the probability a user likes a book for every user and every book would be inefficient.
Loading all of the books form the database and calculating the probability for each one would also be inefficient.
I've written code to predict wether or not a given user will like a given book based on their training data
What does this code look like? Ideally it's some kind of decision tree based on attributes of the book like genre, length, etc, and is technically called a classifier. A simple example:
if ( user.genres.contains(book.genre) ) {
if ( user.maxLength < book.length ) {
print "10% off, today only!"
}
}
print "how about some garden tools?"
Saving the probability a user likes a book for every user and every book would be inefficient.
True. Note that the above decision tree may be formulated as a database query:
SELECT * FROM Books WHERE Genre IN [user.genres] AND Length < [user.maxLength]
Which will give you all books that have the highest probability of being liked by the user, with respect to the training data.

Categories

Resources