How to create a temp boolean field with Django orm - sql

Image I have following models:
class Product(models.Model):
name = models.CharField(max_length=20)
class Receipt(models.Model):
product = models.ForeignKey(Product)
user = models.ForeignKey(User)
I have an input list of product ids and a user. I want to query for each product, whether it's been purchased by this user. Notice I need a queryset with all exist products based on given input because there are other fields I need for each product even not purchased by this user, so I cannot use Product.objects.filter(receipt__user=user).
So can I create a temp Boolean field to present this property in one single query? I am using Django 1.8 and postgresql 9.3
Update requirements:To separate products into two groups. One is bought by this specific user, the other one is not. I don't think any given filter can implement this. This should be implement by creating a new temp field either by annotate or F expression.

I think, you need .annotate() expression as
from django.db.models.expressions import Case, When, Value
product_queryset = Product.objects.annotate(
is_purchased=Case(
When(receipt__user=current_user, then=Value('True')),
default=Value('False')
))
How to access the annotated field?
product_queryset.first().is_purchased

Thx for #JPG's answer.
I just realize except conditional expressions, there's another easy way to do it.
Just using prefetch_related will implement everything in two queries. Although it's double than conditional expressions, but it's still a considerable time complexity solution.
products = Product.objects.filter(id__in=[1,2,3,4,5]).prefetch_related ('receipt_set').all()
Then we can detect user for this product in Python by
for p in products:
print user in [receipt.user_id for receipt in p.purchase_set.all()]

Related

Why related fields use Write function

_name = "my.table"
building_id = fields.Many2one('building', related='floor_id.building_id', readonly=False)
floor_id = fields.Many2one('building.floor')
A user with the read access to 'building' and 'building.floor' tables, tries to create a record in "my.table" If the user chooses building_id and floor_id together an error occurs. The error says that my user has no access to write 'building.floor' table. My question is: why a related field use the write function, what is the difference between the compute and related in this scenario?
Related fields are very simple computed fields. So simple they can be "implemented" with one parameter on field definition. Odoo has generic methods for those fields. For example a lot of developers don't write inverse methods for computed fields, which inverse the compute method, because the simply don't need it. But without it and without storing the computed field, Odoo sets the field readonly.
Related fields have a generic inverse method. In your case changing building_id when there was already a floor_id chosen, Odoo will write the building_id on that floor_id.building_id, because that's how related fields work (i know that's not the best explanation).
The user obviously has no write/update rights on builiding.floor model and that's why there will be the access error message in the end, because Odoo wants to write the new building on the floor.
Seems to me you want to filter the floors by buildings, but you shouldn't use a related field for that. Just put a domain on floor_id which filters by the chosen building_id:
floor_id = fields.Many2one('building.floor', domain="[('building_id', '=?', building_id)]")
You could also use domain operator =, but =? will show all floors when no building was set yet.

Odoo 10 - How to retrieve associated stock_picking name (if such stock_picking exists) from account_invoice_line

I would like to include information about the specific delivery slip in which an invoice line was delivered or is going to be delivered.
Is it possible to retrieve "name" field from the "stock.picking" associated to a given "account_invoice_line"?
Which would be the easiest way to achieve that?
This code provides a new field for sale_order_line_ids in account_invoice_line:
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
sale_order_line_ids = fields.Many2many('sale.order.line', 'sale_order_line_invoice_rel', 'invoice_line_id', 'order_line_id', string='Sale Order Lines', readonly=True);
I would like to be able to get the stock_picking name for that specific account_invoice_line:
I see the following fields in tables:
Table procurement_order
Field: sale_line_id
Field: purchase_line_id
Also:
Table stock_move
Field: picking_id
Field: procurement_id
Field: purchase_line_id
So I need to go backwards but it seems feasible and not complex to get the picking_id.
How could this field be implemented in account_invoice_line model?
It's a little bit of a stab in the dark, but you ought to be able to use this or something very similar:
# Assuming `invoice_line_id` is an individual `account.invoice.line` record
invoice_line_id.sale_order_line_ids.mapped('procurement_id').mapped('move_ids').mapped('picking_id')
You can see in the ORM Documentation that mapped is used to get data for a record or recordset. It's extremely useful when you might have many lines and you want to gather data for all of them.
In this case, the above line would return a browse recordset of all stock.picking records linked to any of the Sales Order Lines belonging to that Invoice Line.
Note: It's possible you may get more data than you want from this, so you'll have to do the testing on your own to confirm it's only returning what you expect.

Co dependent fields in Odoo 9.0 view

Hello everybody and thanks for taking the time to read my question:
I need to make two fields update on each other changes in my view, let's say one of them list's ingredients and the other lists food requirements
requirements = fields.Selection([(0,"Vegan"),(1,"Lactose intolerant")])
ingredients_id = fields.Many2Many(comodel_name="sample.ingredients")
What i need is to update ingredients_id's domain to show only those who match a requirement and vice versa, if you happend to select and ingredient the other field selecting the proper requirement. I'm thinking about making field A a computed field depending on fieldB and then add an on_change to field B that updates field A. But I'm pretty certain that will turn into some kind of infinite loop situation. Is that my only option or am I missing something obviuos?
Use #api.depends decorator and pass both fields as parameters in the decorator. This will trigger function every time on change on both values and will be dependent on each other.
#api.depends('requirements','ingredients_id')
def function (self): ....
do something....
return

Few questions about Grails' createCriteria

I read about createCriteria, and kind of interested on how these works, and its usability in providing values for dropdown box.
So say, i have a table in the database, Resource table, where i have defined the table in the domain class called Resource.groovy. Resource table has a total of 10 columns, where 5 of it are
Material Id
Material description
Resource
Resource Id
Product Code
So using the createCriteria, and i can use just like a query to return the items that i want to
def resList = Resource.createCriteria().list {
and {
eq('resource', resourceInstance)
ne('materialId', '-')
}
}
Where in the above, i want to get the data that matches the resource = resourceInstance, and none of the materialId is equal to '-'.
I want to use the returned data from createCriteria above on my form, where i want to use some of the column on my select dropdown. Below is the code i used for my select dropdown.
<g:select id="resourceId" name="resourceId"
from="${resList}"
disabled="${actionName != 'show' ? false : true}" />
How do i make it so that in a dropdown, it only shows the values taken from column Product Code? I believe the list created using createCriteria returns all 10 columns based on the createCriteria's specification. But i only want to use the Product Column values on my dropdown.
How do i customize the data if in one of the select dropdown in my form, i wanted to show the values as "Resource Id - Resource Description"? The values are combination of more than 1 columns for one select dropdown but i don't know how to combine both in a single select dropdown.
I read that hql and GORM query are better ways of fetching data from table than using createCriteria. Is this true?
Thanks
First of all refer to the document for using select in Grails. To answer all questions:
Yes, the list to select from in the dropdown can be customized. In this case it should be something like from="${resList*.productCode}"
Yes, this can be customized as well with something like
from="${resList.collect { \"${it.resourceId} - ${it.resourceDesc}\" } }"
It depends. If there are associations involved in a domain then using Criteria will lead to eager fetches which might not be required. But with HQL one gets the flexibility of tailoring the query as needed. With latest version of Grails those boundries are minimized a lot. Usage of DetachedCriteria, where queries etc are recommended whereever possible. So it is kind of mixing and matching to the scenario under consideration.

Rails Custom Model Functions

I'm in a databases course and the instructor wants us to develop an e-commerce app. She said we can use any framework we like, and now that we're halfway through the semester she decided that Rails does too much and wants me to explicitly write my SQL queries.
So, what I'd like to do is to write my own functions and add them to the models to essentially duplicate already existing functionality (but with SQL that I wrote myself).
So the questions then become:
How do I execute manually created queries inside the model?
How do I stuff the results into an empty object that I can then return and work with inside the view?
Also, I'm aware of what terrible practice this is, I just don't want to start all over in PHP at this point.
I think, you should know 2-3 really necessary methods, to use it.
(assume we have at least 2 models, Order and User(customer for order))
For example, just to run query on your database use this:
Order.connection.execute("DELETE FROM orders WHERE id = '2')
to get number of objects from your database, the best way is use method "count_by_sql", it's scalable. I'm using it in my projects, where table has over 500 thousands records. All work to count application gives to database, and it did it much more efficient than app.
Order.count_by_sql("SELECT COUNT(DISTINCT o.user_id) FROM orders o")
this query gets number of all uniq users who has an order. we can "JOIN ON" tables, order results using "ORDER BY" and group results.
and the most often use method: find_by_sql
Order.find_by_sql("SELECT * FROM orders")
it returns to you an array with ruby objects.
Lets say you have a purchase
class Purchase < ActiveRecord:Base
def Purchase.find(id)
Purchase.find_by_sql(["Select * from purchases where id=?", id])
end
end
Maybe you want the products for a particular purchase. You can manually define the purchased_items in your Purchase model.
class Purchase < ActiveRecord:Base
def purchased_items
PurchasedItem.find_by_sql(["Select * from purchased_items where purchase_id=?",self.id])
end
end
So for example, in your controller where you now want to get the purchased items for a particular purchase you can now do this
#purchase = Purchase.find(params[:id])
#purchased_items = #purchase.purchased_items
If you need a more raw connection to the database, you can look into ActiveRecord:Base.connection.execute(sql)