I have a model called participants as below
class participants(models.Model):
username= models.CharField(max_length =50)
votes = models.IntegerField(default=0)
voted_by = ?
Votes is the total number of votes given by users and single user can vote multiple times. If the user have voted then the user should wait 1 hour to vote again. Now i am wondering, how can i store users id in a way that it would be easier to know who voted how many times and the recent date and time the user have voted.
Can someone suggest me or refer some examples that i can solve this problem.
You can create another model (eg. VotesHistory)...
class VotesHistory(models.Model):
class Meta:
verbose_name = "Vote Log"
verbose_name_plural = "Vote Logs"
time = models.DateTimeField(auto_now=True, verbose_name="Time")
uid = models.IntegerField(verbose_name="Voter's UserID")
pid = models.IntegerField(verbose_name="Voted UserID")
Now, when user 1 will vote user 2, you can create an entry such as,
VotesHistory(uid=user1.id, pid=user2.id).save()
This kind of problem is generally solved by using a ForeignKey reference.
# class name should begin with a capital letter and should be singular for a model
class Participant(models.Model):
username = models.CharField(max_length =50)
class Vote(models.Model)
vote_to = models.ForeignKey(Participant, on_delete=models.CASCADE, related_name='vote_to')
voted_by = models.ForeignKey(Participant, on_delete=models.CASCADE, related_name='voted_by')
date_time = models.DateTimeField(auto_now=True)
Each vote by a participant would be a row in the Votes table or an object of type Vote.
Something like,
vote = Vote(vote_to=some_participant_object,
voted_by=someother_participant_object)
vote.save()
auto_now=True means the value will be added when the object gets created so you don't have to handle when the vote was cast.
You can then query the number of votes cast by a particular participant using the ORM.
A basic filter query should be enough. Get all the votes by a particular participant.
Something like,
# just as an idea here, the next lines might not be perfect
votes = Vote.objects.filter(voted_by__id=some_participant_id)
# or
votes = Vote.objects.filter(voted_by=some_participant_object)
# check the timestamp of the last vote and build logic accordingly
This way it'll be easier to write ORM queries to count the number of votes a particular participant has or the number of votes a particular participant has cast.
Related
i have this model:
class Person:
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
sexe = models.TextChoices('M', 'F')
arrival_date = models.DateField(max_length=30)
reason = models.CharField(max_length=30)
It turns out that the same person can be registered several times (only the arrival date and the reason change).
I would like to make a query that lists distinctly persons. For example, if a person is registered many times, he will be selected only once.
How can i do it ? Thanks.
you can get data in this way:
Person.objects.values_list('first_name', 'last_name', 'sexe').distinct()
for mysql
Person.objects.filter(positive = 1).order_by().values('first_name').distinct()
for Postgre:
Person.objects.order_by('first_name').distinct('first_name')
Documentation Here
I want to fetch name of movie with maximum rated movie with minimum 5 people rated in django.
My code :
model.py
class Movie(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=100)
vote_count = models.IntegerField()
class Watchlist(models.Model):
userid = models.IntegerField()
movie_id = models.ForeignKey(Movie, on_delete=models.CASCADE)
rating = models.IntegerField()
what will be query to get movie with highest rating with minimum 5 people ?
I propose that you make some changes to your model. Normally ForeignKeys do not end with an id suffix, since Django will add a "twin field" with an _id suffix that stores the value of the target field. Furthermore you probably better make a ForeignKey to the user model. If you do not specify a primary key yourself, Django will automatically add an field named id that is an AutoField, hendce there is no need to add that manually. Finally you do not need to store the vote_count in a field of the Movie, you can retrieve that by counting the number of related Rating objects:
from django.conf import settings
class Movie(models.Model):
title = models.CharField(max_length=100)
class Rating(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete.models.CASCADE)
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
rating = models.IntegerField()
Then we can retrieve the highest rated movie with:
from django.db.models import Avg, Count
higest_rated = Movie.objects.annotate(
rating=Avg('rating__rating'),
votes=Count('rating')
).filter(votes__gte=5).order_by('-rating').first()
Here the votes__gte=5 will filter such that it will only obtain Movies with five or more votes, and we order by rating in descending order.
I'd modify the model, moving out Rating entity related fields from Watchlist and Movie.
Add the "Rate" class, and then filter by two conditions:
Count(Rate for the exact Movie) > minimum threshold(e.g. 5)
AVG(rating score for the exact Movie) > minimum threshold(e.g. 5)
or, if you need top-rated movies, use Order by as it described in that answer
In your case, you could use Count and Average with Watchlist.Rating field
I have three models:
Course
Assignment
Term
A course has a ManyToManyField which accesses Django's default User in a field called student, and a ForeignKey with term
An assignment has a ForeignKey with course
Here's the related models:
class Assignment(models.Model):
title = models.CharField(max_length=128, unique=True)
points = models.IntegerField(default=0, blank=True)
description = models.TextField(blank=True)
date_due = models.DateField(blank=True)
time_due = models.TimeField(blank=True)
course = models.ForeignKey(Course)
class Course(models.Model):
subject = models.CharField(max_length=3)
number = models.CharField(max_length=3)
section = models.CharField(max_length=3)
professor = models.ForeignKey("auth.User", limit_choices_to={'groups__name': "Faculty"}, related_name="faculty_profile")
term = models.ForeignKey(Term)
students = models.ManyToManyField("auth.User", limit_choices_to={'groups__name': "Student"}, related_name="student_profile")
When a user logs in to the page, I would like to show them something like this bootstrap collapse card where I can display each term and the corresponding classes with which the student is enrolled.
I am able to access all of the courses in which the student is enrolled, I'm just having difficulty with figuring out the query to select the terms. I've tried using 'select_related' with no luck although I may be using it incorrectly. So far I've got course_list = Course.objects.filter(students = request.user).select_related('term'). Is there a way to acquire all of the terms and their corresponding courses so that I can display them in the way I'd like? If not, should I be modeling my database in a different way?
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#values
You could use values or values_list here to get the fields of the related model Term.
For example expanding on your current request:
To retrieve all the Terms' name and duration for the Courses in your queryset
Course.objects.filter(students = request.user).values('term__name', 'term__duration')
I am not sure what the fields are of your Term model, but you would replace name or duration with whichever you are trying to get at.
I think it helps you
terms = Terms.objects.filter(....) # terms
cources0 = terms[0].course_set.all() # courses for terms[0]
cources0 = terms[0].course_set.filter(students=request.user) # courses for terms[0] for user
I am new to Django and I am working on a small module of a Django application where I need to display the list of people who have common interest as that of any particular User. So Suppose if I am an user I can see the list of people who have similar interests like me.
For this I have 2 models :
models.py
class Entity(models.Model):
name = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.name
class UserLikes(models.Model):
class Meta:
unique_together = (('user', 'entity'),)
user = models.ForeignKey(User)
entity = models.ForeignKey(Entity)
def __str__(self):
return self.user.username + " : " + self.entity.name
So in the Entity Table I store the Entities in which user can be interested Eg : football, Music, Code etc.
and in the UserLikes I store the relation about which user likes which entity.
Now I have a Query to fetch details about which user has maximum interest like any particular user :
SELECT y.user_id, GROUP_CONCAT(y.entity_id) likes, COUNT(*) total
FROM likes_userlikes x
JOIN likes_userlikes y ON y.entity_id = x.entity_id AND y.user_id <> x.user_id
WHERE x.user_id = ?
GROUP BY y.user_id
ORDER BY total desc;
Problem is how do I write this Query using Django Querysets and change it into a function.
# this gives you what are current user's interests
current_user_likes = UserLikes.objects.filter(user__id=user_id) \
.values_list('entity', flat=True).distinct()
# this gives you who are the persons that shares the same interests
user_similar_interests = UserLikes.objects.filter(entity__id__in=current_user_likes) \
.exclude(user__id=user_id) \
.values('user', 'entity').distinct()
# finally the count
user_similar_interests_count = user_similar_interests.count()
Here the user_id is the user's id you want to query for.
One advice though, it's not good practice to use plural form for model names, just use UserLike or better, UserInterest for it. Django would add plural form when it needs to.
We have custom User model, each instance has multiple interests.
Here is Interest model:
class Interest(models.Model):
name = models.CharField(max_length=50, unique=True)
users = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name="interests", blank=True)
When user going to page, we suggest to contact with other people who have most common interests relatively to this user.
For generation list of users we use:
def suggested_people(user):
queryset = User.objects.custom_filter(is_verified=True).exclude(pk=user.pk).order_by('-date_joined').select_related()
users_sorted = sorted(queryset, key=lambda x: x.get_common_interest(user).count(), reverse=True)
return users_sorted
Method of User-model :
def get_common_interest(self, user):
""" Return a list of string with the interests and the total number remaining """
your_interests = user.interests.values_list('pk', flat=True)
return self.interests.filter(pk__in=your_interests)
But there is a problem that the list is sorted very slowly (for 1,000 users about 8 seconds). Is it possible to somehow simplify or speed up the sorting?
Will be grateful for any advice!
Lets say we have an incoming user named as u for which we want to show suggestions, then the query would be:
from django.db.models import Count
interests_ids = u.interests.values_list('id', flat=True) # select ids of incoming user interests
suggestions = User.objects
.exclude(id=u.id) # exclude current user
.filter(is_verified=True) # filter only verified users
.filter(interests__id__in=interests_ids) # select users based on common interests
.annotate(interests_count=Count('interests')) # count numbers of interests for each user after filtering
.order_by('-interests_count') # order users by max common interests
The suggestions queryset will not contain any user which don't share any common interest with user u. If you still want to show some suggestions if there are no suggestions from above query, then you can filter User based on some other criteria e.g. users living in same country or city.