Django: queryset multiple conditions or gather into new object - python

I need to get all Comments for all Projects that includes a specific User. Meaning, all comments for all projects that a user is member of.
A user can belong to many Projects, and each Project has many Comments.
How should this be done right? So far I have solved it in my template by creating a nested for-loop, but that's not good since I need to sort the result.
I'm thinking something like:
projects = user.projects
comments = Comment
for p in projects:
for c in p.comments:
comments.append(c)
return comments
...does not seem to work.
Any clues?

I think this will do it:
query = Comment.objects.filter(project__user=person)
If the Comment model has a foreign key to project which has a foreign key to user. This will involve a SQL join statement in the database. It's better to do this on the the database because it's far more efficient. Databases are designed exactly to do this.

Related

Does django cache related tables when they are used in filter()

For instance:
e = Entries.objects.filter(blog__name='Something')
Does this cache blog as well or should I still add select_related('blog') to this.
The filter(blog__name='Something') means that Django will do a join when it fetches the queryset. However if you want to access the related blogs you still have to use select_related.
You might find django-debug-toolbar useful so that you can check the queries yourself.
You will see attributes of everything blog and anything farther down as well. Django automagically takes care of it all. But it will do additional queries internally as needed to get blog (beyond blog_id) and anything else. Use select_related to get anything you know you will use. If select_related doesn't work then most of the time prefetch_related will work instead. The difference is that prefetch_related does an extra query for each table. That is still better than letting Django do everything automagically if the query includes more than one record of the main table - i.e., 1 + 1 instead of 1 + n.
I suspect part of the confusion is about filter(). filter and exclude and other ways of getting anything less than all() will reference the other tables in the WHERE part of the query but Django doesn't retrieve fields from those tables unless/until you access them, unless you use select_related or prefetch_related.

Benefits of foreign key over integerfield

I'm not sure if this is an appropriate question here. I know the answer but I don't really know why, and I need proof when I raise this to my team.
We have a number of Blog Posts on a Django Site. It's possible to "clone" one of those blog posts to copy it to another site. The way the current developer did that was to take the pk of the original post and store it as an IntegerField on the cloned post as clone_source. Therefore to get a story's clones, we do:
clones = BlogPost.all_sites.filter(clone_source=pk)
It seems to me that this would be much better structured as a foreign key relationship.
Am I right? Why or why not?
Deleted objects
If you ever decided to delete the original post, you'd need a separate query to handle whatever you expect to do with the cloned posts instead of using the on_delete kwarg of a FK.
Its an extra query
As noted in the comments, foreign keys allow you to traverse the relationships directly through the ORM relationship methods.
Data structure visualisation tools
These won't be able to traverse any further down from an integer field since it will believe it is at a leaf node.
Throughout all of this though, the elephant in the room is that a "clone" is still just duplicated data so I wonder why you don't just let a blog post be referenced more than once then you don't need to worry about how you store clones.

Partial Query of a django JSONField

I have a model with a django JSONField. The JSONField has a key called 'name'. I want to search across my model, for users whose names contain Foo; something like :
User.objects.filter(jsonfield['name']__icontains='foo')
As far as I have researched there is no easy way to do this. My next alternative is to add a new column for jsonfield['name'] so I can search it. Although the fix I am looking for needs to be quick, I am also open to know my more involved options so I can refactor later. Thank you.

SQL Alchemy: Relationship with grandson

I'm building a SQL Alchemy structure with three different levels of objects; for example, consider a simple database to store information about some blogs: there are some Blog object, some Post object and some Comment objects. Each Post belongs to a Blog and each Comment belongs to a Post. Using backref I can automatically have the list of all Posts belonging to a Blog and similarly for Comments.
I drafted a skeleton for such a structure.
What I would like to do now is to have directly in Blog an array of all the Comments belonging to that Blog. I've tried a few approaches, but they don't work or even make SQL Alchemy cry in ways I can't fix. I'd think that mine is quite a frequent need, but I couldn't find anything helpful.
Colud someone suggest me how to do that?
Thanks.
I think you can use an association proxy
class Blog(Base):
comments = association_proxy('posts', 'comments')
You need to use join:
comments = session.query(Comment).join(Post).filter(Post.blog == b1).all()

How to perform a query in django that selects all projects where I am a team member of?

I have the concept of a team in my django app.
class Team(models.Model):
name = models.CharField(max_length=200)
#snip
team_members = models.ManyToManyField(User)
I would like to fetch all teams the currently logged in user is member of. Something along the lines of
Team.objects.all().filter(request.user.id__in = team_members.all())
This obvious doesn't work. Does anyone have some suggestions on how to do such query without going directly to sql? I did look at the django documentation of "in" queries, but I couldn't find my use case there.
Many thanks!
Nick.
You don't need in here, Django handles that automatically in a ManyToMany lookup.
Also, you need to understand that the database fields must always be on the left of the lookup, as they are actually handled as parameters to a function.
What you actually want is very simple:
Team.objects.filter(team_members=request.user)
or
request.user.team_set.all()

Categories