django - Dynamically add computed column to queryset - django

I have a database table containing 4 integer columns representing version information - Major, Minor, Cust, Rev.
I'd like to represent these as a single column in my form, with relevant padding. So:
0, 1, 2, 3 = [0.01.002.0003].
I realise that there are several ways to use SQL to do this, but I'm curious as to whether it's possible to do it on the django side? So, after:
queryset = MyModel.objects.all()
...can I then extend the queryset with an additional calculated field? Later I pass the Queryset to be serialized, and I need the calculated field present at this stage, so I don't think an attribute will work.

annotate should help you:
http://docs.djangoproject.com/en/dev/ref/models/querysets/#annotate-args-kwargs

Related

Django: ValueError: Prefetch querysets cannot use raw(), values(), and values_list()

I am trying to run prefetch as below and gives me error: Prefetch querysets cannot use raw(), values(), and values_list().
queryset = SymbolList.objects.prefetch_related(
Prefetch('stock_dailypricehistory_symbol',queryset = DailyPriceHistory.objects.filter(id__in=[1,2,3,4]).values('close','volume'))).all()
DailyPriceHistory model has lot of columns, i only want close and volume
Here id__in=[1,2,3,4] is just shown for example, it can go upto 10000+ ids at a time.
You can indeed not make use of .values(…) [Django-doc] and .values_list(…) [Django-doc] when prefetching. That would also result in extra complications, since then Django has more trouble to find out how to perform the "joining" at the Django/Python level, if this is even possible.
You however do not need to use .values(…) to limit the number of columns you fetch, you can use .only(…) [Django-doc] instead. .only(…) will only fetch the given columns and the primary key immediately in memory, and will "postpone" fetching other columns. Only if you later need these columns, it will make extra queries. This is thus a bit similar how Django will only fetch the related object of a ForeignKey in memory when you need it with an extra query.
queryset = SymbolList.objects.prefetch_related(
Prefetch(
'stock_dailypricehistory_symbol',
queryset = DailyPriceHistory.objects.filter(
id__in=[1,2,3,4]
).only('close', 'volume', 'symbol_id')
)
)
The symbol_id is the column of the ForeignKey that refers from the DailyPriceHistory to the SymbolList model, this might be a different field than symbol_id. If you do not include this, Django will have to make extra queries to find out how it can link DailyPriceHistory to the corresponding SymbolList, and this will only slow down processing with extra queries, therefore you better include this as well.

Get models in Django that have all of the values in ManyToMany field (AND-query, no reverse lookups allowed)

I have such a model in Django:
class VariantTag(models.Model):
saved_variants = models.ManyToManyField('SavedVariant')
I need to get all VariantTag models that have saved_variants ManyToMany field with exact ids, say (250, 251), no more, no less. By the nature of the code that I am dealing with there is no way I can do reverse lookup with _set. So, I am looking for a query (or several queries + additional python code filtering) that will get me there but in such a way:
query = Q(...)
tag_queryset = VariantTag.objects.filter(query)
How is it possible to achieve?
I should probably stress out: supplied saved variants (e.g. (250, 251) should be AND - ed, not OR - ed.
Use in lookup
tag_queryset = VariantTag.objects.filter(saved_variants__in=[250,251])
So far I was able to achieve AND result by the following code:
tag_ids = VariantTag.objects.filter(variant_tag_type__name=tag_data['tag'],
saved_variants__in=saved_variant_ids).values_list('id', flat=True).distinct()
for tag_id in tag_ids:
saved_variants = list(VariantTag.objects.get(id=tag_id).saved_variants.all().values_list('id', flat=True))
if all(s in saved_variant_ids for s in saved_variants) and len(saved_variants) == len(saved_variant_ids):
return VariantTag.objects.get(id=tag_id)
So, I am doing the following:
Getting the OR - result
Iterating over the resulting ids of the retrieved model and for each one of them getting all of the ids of the ManyToMany field
Checking if all of the obtained ids of the ManyToMany field are in the required ids list (saved_variant_ids)
If yes - get the model by the id: VariantTag.objects.get(id=tag_id)
In my case there will be only one such model that have the required ids in ManyToMany field. If it is not the case for you - just append the ids of the model (in my case tag_id) to a list - then make a query for all of them.
If anyone has more concise way of doing AND ManyToMany query + code, would be interesting to see.

Django: how to query all values in an array?

I have a checkbox with multiple values. For example, hobbies. When the user choose some hobbies, he wants to see the person who has all those hobbies.
I dont go into details for sake of clarity so here's how I read all the checked values and put them in my "big" query, which is, as you may guess: q:
hobbies2 = [int(l) for l in g.getlist('hobbies2')]
if len(hobbies2):
q = q & Q(personne__hobbies2__in=hobbies2)
The problem is that it returns all persons who have a hobby in common (i.e. it's like "or", not "and").
How to get all those many to many values with a and?
The __in operator is for filtering by a set. It is not meant for checking multiple values at once in a many-to-many relationship.
It literally translate to the following in SQL:
SELECT ... WHERE hobbies IN (1, 3, 4);
So you'd need to build your query using AND conditions. You can do this with consecutive filters:
queryset = Personne.objects.all()
# build up the queryset with multiple filters
for hobby in hobbies2:
queryset = queryset.filter(hobbies2=hobby)

Why does values query set not match model attributes

Using django 1.7, python 3.4, and postgres 9.4.
When i query a model's attribute directly it returns the proper value.
When i query the same model using .values(), it returns improper value.
For example:
>>>bomitem = self.itemproduction.billOfMaterials()
>>>for x in bomitem:
>>> x.ratio
>>>>50
>>>>20
>>>>bomitem.values('ratio')
>>>>[{'ratio': 5}, {'ratio': 2}]
Self and itemproduction are a OneToOneField relation.
ItemProduction.billOfMaterials() overrides Product.billOfMaterials()
def billOfMaterials(self):
bom = self.inventoryItem.product.billOfMaterials()
for x in bom:
x.ratio = x.ratio * self.qty
return bom
This basically takes a Product's Bill of Materials (recipe list) and figures the expected Bill of Materials for Production of n amount of a Product.
Also, when i try to filter on bomitem, the resulting queryset has same improper values.
>>>>bomitem.get(component=x)
>>><BOM: Product One: 5>
Why this erratic behavior?
The value in the database is is what you see with .values('ratio')
If you want the value to be x.ratio = x.ratio * self.qty, you'll have to save that model instance into the database after it has been initialiazed with your Python code with the calculation
A better approach would be to use a different field, one for ratio, and one for the calculated values you need (and decide if you want to save them into the DB or calculate on the fly, unless required, it's usually better not to store any calculated fields, that way your data cannot be inconsistent in the DB)

django queryset datetime values substraction

I have model with following field.
date = models.DateTimeField(auto_now_add=True)
When querying such model i`d like to have additional column that would keep difference between current date and previous one. So for 10 rows it would have 9 values, first one would be None. Are there any ways of achieving this with querysets? or maybe i should mess around and create additional list that would hold such differences before i pass queryset to template?
Please advise.
Create a property on the model that calls get_ {next,previous}_ by_*() and returns the timedelta. For advanced functionality, implement caching.