Getting foreign key values from Django values() - python

I am getting data objects from Django models using
tabledata=Entity.objects.filter(quarter=1)
Using this method, I am able to extract the values of the objects specified by the foreign key like so
tabledata[0].creator.name
However when I changed the code to
tabledata=Entity.objects.filter(quarter=1).values()
I can extract only foreign key values but not the values of the object data linked with the foreign key. Something like
tabledata[0][creator][name] does not work
Is there a way to extract the values this way?

You can use lookup in .values() like this:
entities = Entity.objects.filter(quarter=1).values('creator__name')
print(entities[0]['creator__name'])
You can fetch other fields too if you need:
Entity.objects.filter(quarter=1).values('creator__name', 'direct_field', 'another_direct_field')

This is one of the many reasons why using .values() [Django-doc] is not a good idea: it erodes the logical layer of the model.
You can use .annotate(…) [Django-doc] to add the name to the values:
from django.db.models import F
tabledata = Entity.objects.filter(quarter=1).annotate(
creator_name=F('creator__name')
).values()
Then it will appear under the 'creator_name' key in the dictionary.
But using .values() is often only useful in specific usecases. For example a GROUP BY on a specific value, or in a subquery. You should make use of serializers if you want to make JSON for a given model.

Related

How to get all values for a certain field in django ORM?

I have a table called user_info. I want to get names of all the users. So the table has a field called name. So in sql I do something like
SELECT distinct(name) from user_info
But I am not able to figure out how to do the same in django. Usually if I already have certain value known, then I can do something like below.
user_info.objects.filter(name='Alex')
And then get the information for that particular user.
But in this case for the given table, I want to get all the name values using django ORM just like I do in sql.
Here is my django model
class user_info(models.Model):
name = models.CharField(max_length=255)
priority = models.CharField(max_length=1)
org = models.CharField(max_length=20)
How can I do this in django?
You can use values_list.
user_info.objects.values_list('name', flat=True).distinct()
Note, in Python classes are usually defined in InitialCaps: your model should be UserInfo.
You can use values_list() as given in Daniel's answer, which will provide you your data in a list containing the values in the field. Or you can also use, values() like this:
user_info.object.values('name')
which will return you a queryset containing a dictionary. values_list() and values() are used to select the columns in a table.
Adding on to the accepted answer, if the field is a foreign key the id values(numerical) are returned in the queryset. Hence if you are expecting other kinds of values defined in the model of which the foreign key is part then you have to modify the query like this:
`Post.objects.values_list('author__username')`
Post is a model class having author as a foreign key field which in turn has its username field:
Here, "author" field was appended with double undersocre followed by the field "name", otherwise primary key of the model will be returned in queryset. I assume this was #Carlo's doubt in accepted answer.

Group by foreign key as boolean in Django

I have a model in which I have a ForeignKey and an IntegerField.
I want to sum the integer field grouped by the foreign key but the foreign key can have many values. I am only interested in knowing if the foreign key has a 'real value' or is none. So the foreign key should be interpreted as a boolean.
I could make two queries:
a = Model.objects.filter(parent=None).aggregate(Sum('amount'))
b = Model.objects.exclude(parent=None).aggregate(Sum('amount'))
but isn't it less memory demanding to make something like
c = Model.objects.values('parent__as_bool').annotate(Sum('amount'))
if it's possible?
You can always use .extra, like this:
.extra(select={'parent_is_null': "parent is NULL"})
see docs for more examples
Your second option isn't valid because you need to filter the queryset before asking for values, and to specify what you're calling your annotation. As far as treating a foreignkey as a boolean is concerned you're looking for isnull. So you end with something like:
c = Model.objects.filter(parent__isnull=False).values().annotate(amount_sum=Sum('amount'))

Django - Following ForeignKey relationships "backward" for entire QuerySet

is it possible to follow ForeignKey relationships backward for entire querySet?
i mean something like this:
x = table1.objects.select_related().filter(name='foo')
x.table2.all()
when table1 hase ForeignKey to table2.
in
https://docs.djangoproject.com/en/1.2/topics/db/queries/#following-relationships-backward
i can see that it works only with get() and not filter()
Thanks
You basically want to get QuerySet of different type from data you start with.
class Kid(models.Model):
mom = models.ForeignKey('Mom')
name = models.CharField…
class Mom(models.Model):
name = models.CharField…
Let's say you want to get all moms having any son named Johnny.
Mom.objects.filter(kid__name='Johnny')
Let's say you want to get all kids of any Lucy.
Kid.objects.filter(mom__name='Lucy')
You should be able to use something like:
for y in x:
y.table2.all()
But you could also use get() for a list of the unique values (which will be id, unless you have a different specified), after finding them using a query.
So,
x = table1.objects.select_related().filter(name='foo')
for y in x:
z=table1.objects.select_related().get(y.id)
z.table2.all()
Should also work.
You can also use values() to fetch specific values of a foreign key reference. With values the select query on the DB will be reduced to fetch only those values and the appropriate joins will be done.
To re-use the example from Krzysztof Szularz:
jonny_moms = Kid.objects.filter(name='Jonny').values('mom__id', 'mom__name').distinct()
This will return a dictionary of Mom attributes by using the Kid QueryManager.

use IDs instead of instances to create new objects with foreign keys

I want to create a new Django ORM object with three foreign keys. I got the IDs of the foreign rows already, and I mean - that's all I need to fill the foreign key columns in my new row, right? However, I don't seem able to create the new row without hitting the DB three times to instantiate objects out of those IDs.
So what I need to do:
foreign_object = models.ForeignObject.get(pk=foreign_object_id)
a = models.Object1.get_or_create(f = foreign_object)
What I'd like to do:
a = models.Object1.get_or_create(f_id = foreign_object_id)
f_id however is not a field Django recognizes. If I just assign foreign_object_id to f (I think I recall this works in some cases), Django complains that it wants a ForeignObject instance instead of an int.
Any way to do this?
You need to use the double-underscore notation in this case
eg
a = models.Object1.get_or_create(f__pk=foreign_object_id)

Appengine - Possible to get an entity using only key string without model name?

I want to be able to have a view that will act upon a number of different types of objects
all the view will get is the key string eg:
agpwb2xsdGhyZWFkchULEg9wb2xsY29yZV9hbnN3ZXIYAww
without knowing the model type, is it possible to retrieve the entity from just that key string?
thanks
No superclassing required, just use db.get():
from google.appengine.ext import db
key_str = 'agpwb2xsdGhyZWFkchULEg9wb2xsY29yZV9hbnN3ZXIYAww'
entity = db.get(key_str)
If you design your models so they all use a common superclass it should be possible to retrieve your objects by using something like:
entity = CommonSuperclass.get('agpwb2xsdGhyZWFkchULEg9wb2xsY29yZV9hbnN3ZXIYAww')

Categories

Resources