I am trying to understand the use of prefetch_related and select_related for optimization. I learned somewhere in the blog that one of the where to use prefetch and select is, prefetch_related is used for reverse relation and select_related for the forward relation. In my case there is Resume model and Education Model. Education model has FK of resume with the related_name for reverse relation instead of writing additional _set when querying. I need to list all the education of an requested user with the requested user resume. I could do this without those optimization techniques as follow
education_instance = Resume.objects.get(applicant=request.user).educations.all()
When I tried to use the following instead, I get the error I stated in the title
education_instance = Resume.objects.filter(applicant=request.user).prefetch_related('educations')
Here is my model
class Resume(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=False, null=False, help_text="Full Name")
class Education(models.Model):
resume = models.ForeignKey(Resume, related_name='educations')
name = models.CharField(max_length=100, blank=False, null=False, help_text="Name of an institution")
Can anyone make me clear on select_related and prefetch_related with simple layman terms ? I could not understand the issue I am getting
From the Exception that you provided, you are trying to call .prefetch_related() on object Resume, not Resumes QuerySet.
So, make sure you run
Resume.objects.filter(applicant=request.user).prefetch_related('educations')
not
Resume.objects.get(applicant=request.user).prefetch_related('educations')
Actually you should use select_related in this case.
As far as i know prefetch_related is used for many to many relations and it makes two queries to retrieve objects while select_related is used for normal fk or one to one relations and it fetched all objects in one query using joins.
first of all go through this [document of prefetch_related][1]
[1]: https://docs.djangoproject.com/en/1.11/ref/models/querysets/#prefetch-related then you will find that you can not use it like this
you have to apply on Education modal
education_instance = Education.objects.filter(resume__applicant == request.user).prefetch_related('resume')
hope this will help you.
Related
I've been reading through the Django documentation and looking over some of the other answers on the site for a couple of hours now, yet I still can't get it to sink in. I know this isn't Django specific, but the examples I use will be from a Django project.
My question boils down to when is it appropriate to use each:
Many-to-many relationships
Many-to-one relationships
One-to-one relationships
One-to-one, more or less makes sense to me.
Now for the other two. While I understand the differences between them in isolation, when it comes to using them practically in a project, I get confused. Here is an example:
class User(AbstractUser):
pass
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.TextField()
class Watchlist(models.Model):
user = models.ForeignKey(User, related_name='watchlist', on_delete=models.CASCADE)
item = models.ManyToManyField(Listing)
class Comment(models.Model):
user = models.ForeignKey(User, related_name='comments', on_delete=models.SET_NULL)
comment = models.TextField()
Would this be the correct use of Many-to-one(ForeignKey) and Many-to-many?
Should Watchlist.item be a ForeignKey? Or is M2M correct?
Wouldn't it simplify to make the 'Watchlist' part of the User class? (give them an empty list to populate with listing ID's)
Why is Watchlist.user not a One-to-one relationship, if each watchlist belongs to a single user, and a user can only have one list?
Apologies for my stupidity, I just can't get this to sink in!
Thank you.
edit: Context, the models are from a 'learning' project I was working on intended to be an auction site, similar to eBay. The watchlist is sort of a 'wish' list... for the user to watch an item, not for site to watch a user!
To explain it simply these django-models or objects represents tables in your database and the fields are like the columns in them. So with a one-to-one relation you can only have one row in one table relating to one row in another table. For example one user in the user table (represented by one row) can only relate to one row in a profile table. But your user can have many comments, so this would be a one-to-many/foreignkey relation (if you set unique=true on a fk, it will in practice function as 1:1). If the users can collaborate on writing comments, or for example as here on stackoverflow where users can edit other users comments, that would be a many-to-many relation.
Database design can be complicated/complex, especially using an ORM without basic knowledge of SQL and how it all works beneath. In general it requires a bit of planning even for a simple application.
A version of this question has been asked here several times but none of the answers provided solve my exact problem.
I'm trying to bulk_create a batch of objects of a model with a ManyToMany field.
In this case, the ManyToMany field refers to the same model, though I'd also be interested in the general case.
Let's say this is my model:
class Person(models.Model):
name = models.CharField(max_length=20, blank=True, null=True)
friends = models.ManyToMany("self", related_name="friends_with", null=True)
After bulk_creating a large number of Person objects, I want to add the information who's friends with whom within this group.
Is there a more efficient way to go about this than looping through each new Person and calling .set(friend_pks) or .add(*friend_pks)?
I.e., an analogue of bulk_update.
I've achieved some speed-up by wrapping the loop into with transaction.atomic() (from this answer) but it's still quite slow.
Okay, my post was premature -- it seems that this answers the question.
The key is to bulk_create the through models. In this example:
friends_relation_1 = Person.friends.through(from_person_id=1, to_person_id=2)
friends_relation_2 = Person.friends.through(from_person_id=2, to_person_id=8)
Person.friends.through.objects.bulk_create([friends_relation_1, friends_relation_2, ...])
I know the foreign key concept,Djongo Array field , however is there an alternative?
The issue with the foreign key concept is that I would need to make multiple hits to the database and the issue with Array field is the lack of information and the errors emerging without a known solution.
What I would like to do basically is in fact add multiple instances of a model say comments to a single field in another model but I would like to embed it rather than creating a new table for comments which I tried using an abstract model however it did not work out.
I would like to know any alternative solution.
You can use foreign keys, and to avoid making separate query for every related record you can extract them all at once using prefetch_related - https://docs.djangoproject.com/en/3.1/ref/models/querysets/#prefetch-related :
Returns a QuerySet that will automatically retrieve, in a single batch, related objects for each of the specified lookups.
Code example:
# models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
class Comment(models.Model):
post = models.ForeignKey(Post, models.CASCADE)
text = models.TextField()
# Somewhere else, fetch posts together with related comments:
# It will take 2 requests in total
# - one to fetch posts, another to fetch all related comments
for post in Post.objects.all().prefetch_related('comment_set'):
print([c.text for c in post.comment_set.all()])
I know I am not the first one to ask this question but I can't find a solution. I have the following model
class Flat (models.Model):
user = models.ForeignKey(User)
agent = models.ForeignKey(User, null=True, blank=True, related_name='agent')
And I want to retrieve all Users who are associated to a flat which has a specific agent, knowing that agent has a OneToOne relationship with the User model. So I used the following lookup following the docs :
clients = User.objects.filter(flat__agent=specific_agent)
But I get the following error :
Cannot resolve keyword 'flat' into field
My guess is that the problem comes from the fact I have two FK - with the User model in my Flat model. So I tried to use related_name and related_query_name, but nothing changes.
Any idea on where the problem could come from ? Thanks !
I have a silly Job model in my app:
class Job(models.Model):
# working info
user = models.ForeignKey(User)
company = models.CharField(max_length=100, blank=True)
department = models.CharField(max_length=100, blank=True)
inaugural_date = models.DateField('inaugural date', blank=True)
resignation_date = models.DateField('resignation date', blank=True)
the above model is exactly what I have in my app and this model is used to let user get their college, nothing more.
It works, but I think there must be a better way to design this model, because suppose I want get all the users within the same company and same department in same period of time, its not that easy.
Please help me to reconstruct this model, any suggestion will be appreciated!
This should work:
User.objects.filter(
job_set__company__iexact="wwwww",
job_set__department__iexact="xxxxx",
job_set__inaugural_date__gt=yyyy,
job_set__resignation_date__lt=zzzz
)
It doesn't seem that complex to me, such query wouldn't be easy if you think in SQL terms, at least for me :)
Depends how much you predict on growing and what backend you use. For relation db (mysql/postgres etc) I would create a separate model for departments and companies and also create join tables for them in order to make my job easier later on.
Your model looks fine.
Even though Django model is not Anemic , I usually look it as pure data structure without too much logic. So I think
get all the users within the same company and same department in same period of time
is a logic which should not be a concern of your model, which also means, it should not influence your model design too much IMHO.
Model should be kept simple and thin, so that it can be adopted and adapted in/to different kinds of logic. If you try to make you model structure suitable to a specific logic, you will easily find yourself entangled with inflating models.
BTW, for complex query, you can fallback to Raw SQL