I have a model called Post which has two fields upvotes and downvotes. Now, upvotes, downvotes are ManyToManyField to a User. This is the model:
class Post(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
content = models.CharField(max_length=1000)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
subreddit = models.ForeignKey(Subreddit, on_delete=models.CASCADE)
upvotes = models.ManyToManyField(Profile, blank=True, related_name='upvoted_posts')
downvotes = models.ManyToManyField(Profile, blank=True, related_name='downvoted_posts')
I have to make a query where I have to get all posts sorted by
total (upvotes) - total (downvotes)
I have tried Post.objects.order_by(Count('upvotes')) to get started but there's an error.
Use QuerySet.annotate() first.
Post.objects.annotate(
total_votes=Count('upvotes')-Count('downvotes')
).order_by('total_votes')
An added benefit of annotate() is that every Post in the queryset gets the total_votes attribute, which you can access later with no additional database query or calculation.
Related
I'm using Django and I want to know how to get objects through 3 models
These are my models
class Participant(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
is_leader = models.BooleanField(default=False)
team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True, related_name="participants")
application_date = models.DateField(auto_now_add=True, null=True)
resolution_date = models.DateField(null=True, blank=True)
accepted = models.BooleanField(default=False)
class Team(models.Model):
name = models.TextField(default="")
is_public = models.BooleanField(default=False)
institution = models.ForeignKey(Institution, on_delete=models.CASCADE, null=True, related_name='teams')
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, null=True, related_name='teams')
class Campaign(models.Model):
name = models.TextField(default="")
description = models.TextField(default="")
initial_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
end_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
qr_step_enabled = models.BooleanField(default=True)
image_resolution = models.IntegerField(default=800)
sponsor = models.ForeignKey(Sponsor, on_delete=models.CASCADE, null=True, related_name='campaigns')
I have the user through a request, and I want to get all campaigns of that user.
I tried doing it with for loops but I want to do it with queries
this is what I had:
user = request.user
participants = user.participant_set.all()
for participant in participants:
participant.team.campaign.name
is there a way to make a query through these models and for all participants?
A user can have many participants, and each participant has a Team, each team has a campaign
The best way is to merge the two modela Team and Campaign in one model.
Something as simple as this should work:
Campaign.objects.filter(team__participant__user=request.user)
The Django ORM is smart enough to follow foreign key relationships in both directions.
Thanks to Daniel W. Steinbrook to guide me to the answer, I had to do this to get the query:
Campaign.objects.filter(teams__participants__user__exact=request.user)
My models:
class User(models.Model):
id = models.UUIDField(primary_key=True)
first_name = models.Charfield()
class Conversation(models.Model):
id = models.UUIDField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
class Message(models.Model):
id = models.UUIDField(primary_key=True)
conversation = models.ForeignKey(Conversation, on_delete=models.PROTECT, null=False)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True, blank=True)
I tried to to order by adding annotate and adding order by. Can some body help me to select all users and order them by the latest message they had. I need user with latest message at to and then accordingly.
Try this
queryset = User.objects.all().order_by(
'-conversation__message__created_at'
).distinct()
I am trying to create models for backend in django rest framework. Most of the developers I saw used two models namely Cart and Cart Items for creating cart which is as follows:
class Cart(models.Model):
owner = models.OneToOneField(User,
related_name="cart",
on_delete=models.CASCADE,
null=True,
blank=True)
number_of_items = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00,
max_digits=5,
decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"User: {self.owner}, items in cart {self.number_of_items}"
class CartItem(models.Model):
cart = models.ForeignKey(Cart,
on_delete=models.CASCADE)
item = models.ForeignKey(Product,
on_delete=models.CASCADE)
quantity = models.IntegerField()
I am confused as to why one has to create two models. What is the actual use for it? And isnt the item should be many to many fields instead of the foreign key because we are supposed to add multiple products on the cart.
Also, why is there number_of_items and also quantity at same time? What is the difference??
My proposed model:
class Cart(models.Model):
owner = models.OneToOneField(User,related_name="cart",
on_delete=models.CASCADE,
null=True,
blank=True)
item = models.ManytoManyField(Product,blank =True, null =True)
number_of_items = models.PositiveIntegerField(default=0)
total = models.DecimalField(default=0.00,
max_digits=5,
decimal_places=2)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
#Saroj Paudel - This is what I had used for my Cart Model in my e-commerce project. I had one model for the cart. That is the cartitem that had a reference to the product_id, user_id, quantity(number of items in the cart), and the date_added.
1 Product can belong to 1 or many cartitem and 1 cartitem can have 1 or many products. So, essentially it's an M2M but I am opting for 1 to Many as I don't see any harm other than the fact that my product_id might be repeating many items for different users but I am ok with that repetition.
class CartItem(TimeStampedModel):
date_added = models.DateTimeField(auto_now_add=True)
quantity = models.IntegerField(default=1)
product = models.ForeignKey(Product, unique=False, on_delete=models.PROTECT)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
What field or fields in model should I be indexing to speed up the following query?
Note this is an existing table with data, if that changes your answer
Query Subscriber.objects.filter(audience=audiencepk).order_by('-create_date')
Models:
class Subscriber(models.Model):
first_name = models.CharField(max_length=15, blank=True)
last_name = models.CharField(max_length=15, blank=True)
audience = models.ForeignKey(Audience, on_delete=models.CASCADE)
create_date = models.DateTimeField(auto_now_add=True)
class Audience(models.Model):
audience_name = models.CharField(max_length=50)
create_date = models.DateTimeField()
store = models.ForeignKey(Place, on_delete=models.CASCADE)
Short answer: It depends
Longer answer: It depends on the data itself, what other queries you need to be supporting, and how write-intensive your system is. Each index you add takes up space and will slow down writes, so it's impossible to just look at a data model and a single query and know what indices to add.
That said, if space and write performance are of no concern and we're only looking at this query. I think the answer is a multi-column index on audience and create_date (in that order).
class Subscriber(models.Model):
first_name = models.CharField(max_length=15, blank=True)
last_name = models.CharField(max_length=15, blank=True)
audience = models.ForeignKey(Audience, on_delete=models.CASCADE)
create_date = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=['audience', '-create_date']),
]
I am deciding on how to track if a user has seen a post in the timeline or not.
There is Post and Comment model like this.
class Comment(models.Model):
author = models.ForeignKey('UserProfile')
title = models.CharField(max_length=255)
text = models.TextField(null=True, blank=True)
date_created = models.DateTimeField()
post = models.ForeignKey('Post', related_name='comments')
class Post(ContentTypeModel):
title = models.CharField(max_length=255)
group = models.ForeignKey('UserGroup', null=True)
date_updated = models.DateTimeField()
Suggestions about best practices on how to track if post has been seen by particular member of a user group will be nice.
I managed to do as was suggested, i.e. adding m2m relation to track who viewed the post:
class Post(models.Model):
...
date_updated = models.DateTimeField()
viewers = models.ManyToManyField('UserProfile', through='PostViewer')
class PostViewer(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
viewer = models.ForeignKey('UserProfile', on_delete=models.CASCADE, related_name='posts_seen')
last_seen = models.DateTimeField(null=True, blank=True, help_text='Is set when user sees the post in details')
class Meta:
unique_together = ('post', 'viewer')
This way i can compare post.date_updated to viewer.last_seen and get desired filtering on who have seen the update/create of Post.