Django models - assign identifier instead of object

Sorry if my question turns out to be stupid, but I'm pretty new to Django and I couldn't find the answer anywhere.

I have the following model:

class BlackListEntry(models.Model): user_banned = models.ForeignKey(auth.models.User,related_name="user_banned") user_banning = models.ForeignKey(auth.models.User,related_name="user_banning") 

Now when I try to create an object like this:

 BlackListEntry.objects.create(user_banned=int(user_id),user_banning=int(banning_id)) 

I get the following error:

 Cannot assign "1": "BlackListEntry.user_banned" must be a "User" instance. 

Of course, if I replaced it with something like this:

 user_banned = User.objects.get(pk=user_id) user_banning = User.objects.get(pk=banning_id) BlackListEntry.objects.create(user_banned=user_banned,user_banning=user_banning) 

everything is working fine. The question arises:

Is my solution getting into the database to retrieve both users, and if so, can this be avoided just by passing identifiers?

+8
python django django-models
source share
2 answers

The answer to your question is YES.

Django will go into the database (at least) 3 times, 2 to retrieve two User objects, and a third to transfer your desired information. This will result in completely unnecessary overhead.

Just try:

 BlackListEntry.objects.create(user_banned_id=int(user_id),user_banning_id=int(banning_id)) 

This is the default name template for the FK fields created by Django ORM. This way you can directly set information and avoid queries.

If you want to query already saved BlackListEntry objects, you can navigate through the attributes using double underscores, for example:

 BlackListEntry.objects.filter(user_banned__id=int(user_id),user_banning__id=int(banning_id)) 

So you get access to properties in Django requests. double underlined. Then you can compare with the attribute value.

Although they are very similar, they work in a completely different way. The first sets the attribute directly, and the second is processed by django, which breaks it into "__" and queries the database correctly, being the second part of the attribute name.

You can always compare user_banned and user_banning with the actual User objects, and not with their identifiers. But for this there is no use if you do not have these objects yet.

Hope this helps.

+10
source share

I really believe that when you bring users, it will go to db ...

To avoid this, you will need to write raw sql for the update using the method described here:

https://docs.djangoproject.com/en/dev/topics/db/sql/

If you decide to go this route, remember that you are responsible for protecting yourself from SQL injection attacks.

Another alternative would be to cache user_banned and user_banning objects.

But, in all likelihood, simply capturing users and creating BlackListEntry will not cause any noticeable performance issues. Caching or executing raw sql will give only a slight advantage. You will probably encounter other problems before this becomes a problem.

0
source share

All Articles