django serialize foreign key objects - python

Serialize django model with foreign key models
Serializing Foreign Key objects in Django
get foreign key objects in a single query - Django
There are couple of question asking for the same thing already. But they are from 2010, and it didn't help me so much. So I figure it maybe been some update to this front since 2010?
On google I found this link, which explain usage of natural keys. However my problem concerns of getting foreign objects from django.contrib.auth.models.User so it doesn't help.
My problem is as following. I want to serialize the QuerySet so I get the foreign key objects also, because I want to pass it as JSON to the client. The serializer from django.core doesn't do that. So in my case to simply the problem I had added another field to the model to contain the value I need from the foreign object. But it however introduce redundant data.
My example model it contains the username which I would like if possible remove, and instead get it by the foreign key.
user = models.ForeignKey(User)
username = models.CharField(max_length=100, null=False)

One potential way around this is to construct your own dictionary object based on the returns of a queryset. You'd do something like this:
queryset = Model.objects.all()
list = [] #create list
for row in queryset: #populate list
list.append({'title':row.title, 'body': row.body, 'name': row.user.username})
recipe_list_json = json.dumps(list) #dump list as JSON
return HttpResponse(recipe_list_json, 'application/javascript')
You need to import json for this to work.
import json

You could use Django REST frameworks' serializers.

Related

Saving and updating nested documents with MongoEngine

I want to implement this structural model to store my data on Mongodb with MongoEngine on flask:
skills = [{"asm":"Assembly",
"flag":False,
"date": datetime},
{"java":"Java",
"flag":False,
"date": datetime}]
So I don't know how I can declare and update this kind of structure.
For updating one object I used:
User.objects(skills=form.skills.data).update_one()
However, I don't know how to update more fields in one shot.
I tried with the code below but it doesn’t work.
now = datetime.now()
User.objects(skills=form.skills).update_one(set__skills = ({'ruby':'Ruby'}, {'flag':'true'},{'date':now}))
What kind of fields should I declare on forms.py?
For what I understood, you need a a nested document (skills) into another (who refers to User in this case). For doing something like this you don't have to update atomically a field but append values to the subdocument and the save everything.
Tryin' to follow your example, in your case should do something like this:
user = User.objects(email=current_user.email).get()
To get the BaseQuery that refers to user X through a certain query filter, in my example the email of the current logged user
user.kskills.append(SubDocumentClass(skillName="name_of_the_skill", status=True, date=datetime.now()))
For append a collection to the subdocument list. (I've appended your field)
user.save()
To save everything

How to filter a Django queryset via text field in the latest corresponding entry in a separate model

I have a model where I needed historical data for a couple specific fields, so I put those fields into a separate model with a foreign key relationship.
Something sort of like this:
class DataThing(models.Model):
# a bunch of fields here...
class DataThingHistory(models.Model):
datathing_id = models.ForeignKey('DataThing', on_delete=models.CASCADE)
text_with_history = models.CharField(max_length=500, null=True, blank=True)
# other similar fields...
timestamp = models.DateTimeField()
Now I'm trying to filter the former model using a text field in the latest corresponding entry in the latter.
Basically if these were not separate models I'd just try this:
search_results = DataThing.objects.filter(text_with_history__icontains=searchterm)
But I haven't figured out a good way to do this across this one-to-many relationship and using only the entry with the latest timestamp in the latter model, at least by using the Django ORM.
I have an idea of how to do the query I want using raw SQL, but I'd really like to avoid using raw if at all possible.
This solution makes use of distinct(*fields) which is currently only supported by Postgres:
latest_things = DataThingHistory.objects.
order_by('datathing_id_id', '-timestamp').
distinct('datathing_id_id')
lt_with_searchterm = DataThingHistory.objects.
filter(id__in=latest_things, text_with_history__icontains=searchterm)
search_results = DataThing.objects.filter(datathinghistory__in=lt_with_searchterm)
This should result in single db query. I have split the query for readability, but you can nest it into a single statement. Btw, as you might see here, foo_id is not a good name for a ForeignKey field.
You would do the same by querying DataThing while referring to DataThingHistory:
search_results = DataThing.objects.filter(datathinghistory__text_with_history__icontains=searchterm)
Check django doc on how to query on reverse relationship.
Edit:
My previous answer is incomplete. In order to search on latest history for each DataThing, you need to annotate on timestamp using Max:
from django.db.models import Max
search_results = search_results.values('field1', 'field2',...).annotate(latest_history=Max('datathinghistory__timestemp'))
This wouldn't give you complete DataThing objects, but you could add as many fields to values as you want.

django query for sorting the data on a field present as foreign key

class abc(xyz):
user = models.ForeignKey(User, max_length=100)
What'll be the django query for sorting the data based on a foreign key field?
I tried with query:
abc.objects.filter(User__user=user).
abc.objects.filter(Q(user__icontains=search_query) ).
I have done this 2 queries, But dont know how to combine & make it work
I don't know how to proceed. Can someone please lend a helping hand?
The first query does not work with your model. Change it to
qs = abc.objects.filter(user=user)
Now, sorting this queryset by user (or user_id or any other user's property which would work)
qs = qs.order_by('user_id')
wouldn't make much sense as all elements in your queryset have the same user.
The second query does not work since icontains is a query that works for strings whereas user is a model instance. The following might work:
abc.objects.filter(user__username__icontains=search_query) # .order_by('user__username')
Generally, you can order by properties that have a (natural) order, like ints, floats, strings, dates, etc. Thus, you can order by sth. like user_id, user__username, user__email, user__date_joined:
abc.objects.all().order_by('user_id') # for instance
I believe you want to sort by user's username. You can do it by:
abc.objects.all().order_by('user__username')
Look at the docs for details.
Note the double underscore '__' here. It is required to separate the foreignkey's field from foreignkey by double underscore while referring foreignkey's field.

Returning Multiple QuerySets in Json Dictionaries via Ajax

I am returning my model as a dictionary from my views.py via the following code
data = serializers.serialize('json', response_dict)
return HttpResponse(data, mimetype='application/javascript')
The thing is that I have a foreign key that in the object and I want the actual value of the object that the foreign key points to, but I just get the ID. I want to try to return the corresponding objects for the ID. One way I have tried is to return a separate list with the corresponding objects for each foreign key with the following code, but it does not work.
#original dictionary that returns id values for foreign keys
data1 = serializers.serialize('json', response_dict)
#The corresponding objects from the foreign key table stored in a parallel list of equal length to response_dict
data2 = serializers.serialize('json', other_list)
data = simplejson.dumps([data1, data2])
#return json dump to template via ajax
return HttpResponse(data, mimetype='application/javascript')
How would I go about returning both the initial dictional and list with corresponding values for the foreign key? I am also open to a better method that gets me the actual object values for each foreign key
I think what you are looking for is a way to serialize relations.
Have a look at:
https://code.google.com/p/wadofstuff/wiki/DjangoFullSerializers#Relations
Also note that simplejson is deprecated as of Django 1.5:
https://code.djangoproject.com/ticket/18023#comment:10
I created a version of the Wad of stuff serializer that works with Django 1.5 a while ago:
https://github.com/kolben/wadofstuff
Eventually in my Django serializer I set use_natural_keys=True and defined the natural keys for the tables whose values I wanted to see. See the tutorial in the Django docs here:
https://docs.djangoproject.com/en/dev/topics/serialization/#natural-keys
This solution works for my specific purposes, but is limited in general. I marked sunn0's answers as the accepted answer because the 'wadofstuff' serializer in this link seems to give a more extensive and general solution.

Queryset filtering using an array of GenericForeignKey objects

Here's the problem.
I have a table that contains records which associate a user with an object that is defined by a GenericForeignKey
I can obtain a list of these objects as such:
association_objects = Association.objects.filter(user = request.user)
This will return an array of objects, and I can access the associated object with
association_object.context
So I can easily make an array of just the context objects
NOW I need to query ALL records of another table that are related to any of the objects in the aforementioned Association array.
In a good and holy universe, I could do something like
Action.objects.filter(context__in = associations)
where context in that table is ALSO a GenericForeignKey
However, GFK's cannot be filtered on their actual key property. You have to filter by both content type and primary key simultaneously...
How the hell do I do this? The only bright idea I had was seperate content_type and id into two separate arrays and do __in filters on both properties, but that doesn't seem like it would actually work.
Anyone got any bright ideas?
from django.contrib.contenttypes.models import ContentType
ct = ContentType.objects.get_for_model(Action)
action_ids = association_objects.values_list("object_id", flat=True)\
.filter(content_type=ct)
actions = Action.objects.filter(pk__in=action_ids)
(assuming your GenericForeignKey consists of a content_type and object_id!)
Try this:
# I assume that association_objects is a QuerySet
association_ids = association_objects.value_list("id", flat=True)
content_type = ContentType.objects.get_for_model(Association)
actions = Action.objects.filter(content_type=content_type,
object_id__in=association_ids)

Categories