Django model has birth_year, birth_month, birth_day and death_year, death_month, death_day fields.
model.py
class person(models.Model):
birth_year = models.SmallIntegerField()
birth_month = models.SmallIntegerField()
birth_day = models.SmallIntegerField()
death_year = models.SmallIntegerField()
death_month = models.SmallIntegerField()
death_day = models.SmallIntegerField()
I have to get the count of persons who lives less than 1 month.
views.py
return render(request, 'report.html', {'count': count})
how can I query in view.py
I hope django expert's help. :)
I have to get the count of persons who lives less than 1 month.
Use DateField:
class Person(models.Model):
birth = models.DateField()
death = models.DateField()
You can use F expressions to do the calculation, like this:
from datetime import timedelta
from django.db.models import F
q = Person.objects.annotate(life_span=F('death') - F('birth'))
.filter(life_span__lte=timedelta(days=29))
.count()
print(f'Number of people {q}')
Here I am assuming anyone who lives less than 29 days to have lived for less than a month.
The concept of a "month" differs based on leap years, etc. If you need that kind of precision, you can add some more filters and logic to the above.
Related
problem context - I've a django model like this.
class UpdateRequests(models.Model):
field_name = models.CharField(max_length=20)
field_new_value = models.CharField(max_length=20)
created_at = models.CharField(max_length=10)
customer_id = models.CharField(max_length=50)
request_status = models.CharField(max_length=20, choices=JOS_STATUS)
request_close_date = models.CharField(max_length=20)
problem statement - I want to fetch all records created with in last 24 hours.
how I was trying - I was trying like this in my view function
time_threshold = datetime.now() - timedelta(days=1)
results = UpdateRequests.objects.filter(created_at__lte=time_threshold,
request_status="Pending").values()
but it is not working and I guess because django __lte , __gte works on DateTimeField() only.
reference - https://docs.djangoproject.com/en/4.1/ref/models/querysets/
Please help me with this, I don't want to change the schema since it's already in the production.
Bruh you stored datetime in charfield created_at = models.CharField(max_length=10) How can db serve you Datetime Object? you have to make changes in Models and create objects again with this
created_at = models.DateTimeField(null=True,blank=True,auto_now_add=True)
auto_now_add=True Will fetch current datetime when you will Create Model object.
I am making a movie rating app. Each movie can be rated by users.
class MovieRating(models.Model):
movie = models.OneToOneField(Movie)
users = models.ManyToManyField(User, through='UserRating')
average_rating = ???
or whichever is better
#property
def average_rating(self):
???
class UserRating(models.Model):
movie_rating = models.ForeignKey(MovieRating)
user = models.ForeignKey(User)
rating = models.PositiveIntegerField(
default=1,
validators=[
MinValueValidator(1),
MaxValueValidator(10)
]
)
review = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
class Meta:
unique_together = ('movie', 'user')
I want to get the average rating of for that movie. Meaning
average_rating = (Total rating by user for a MovieRating) / (Total users of MovieRating)
I can get the total users of a MovieRating by
movie_rating.users.count()
But how do I get the rating of every users in Total? Or else what can I do to get the average rating for a movie?
update:
Now I am doing this way, but I don't know whether this is the right way to go:
def average_rating(self):
if self.users.count() == 0:
return 0.0
rates = 0
rating_list = [user_rating.rating for user_rating in self.userrating_set.all()]
for r in rating_list:
rates = r + rates
return rates / self.users.count()
Django supports aggregation queries, including averaging. In your case you can aggregate on the related field through the object's reverse relation to its intermediary model. Since aggregations are performed natively by the database, they are generally recommended over manually calculating their values.
So in your average rating property method
from django.db.models import Avg
...
#property
def average_rating(self):
return self.userrating_set.aggregate(Avg('rating'))['rating__avg']
Try something like:
sum([rate.rating for rate in movie_rating.userrating_set.all()])
I have been creating a website for a donation service. We currently have a leaderboard that displays all of the users, how many times they have donated, and how many donations they have made. Let's start simple, I need the results to show in descending order so that the highest number is atop the leaderboard.
Here is my models.py with my get_queryset().
class UserListView(ListView):
model = User
template_name = 'leaderboards.html'
def get_queryset(self):
queryset = super(UserListView, self).get_queryset()
return queryset.annotate(
contributions_count=Count('contribution'),
contributions_total=Sum('contribution__amount'),
)
Now I also need a leaderboard exactly like the last but with just the monthly donation leaders.
Any help would be much appreciated.
Edit: Here is my model for Contribution. The amount field is the one that I am concerned with. The date I would like to use is the date it was posted.
class Contribution(models.Model):
amount = models.IntegerField()
date = models.DateField(auto_now_add=True)
notes = models.CharField(max_length=50)
user = models.ForeignKey(User)
With this models:
class Vine(models.Model):
autor = models.ForeignKey(Viner,related_name='autor')
titulo = models.CharField(max_length=450)
estado = models.CharField(choices=ESTADOS_VINE, max_length=30)
objects = models.Manager()
custom_object = managers.VineManager()
and the model for the votes
class Voto(models.Model):
user = models.ForeignKey(MyUser)
submit_date = models.DateTimeField(auto_now_add=True)
vine = models.ForeignKey(Vine)
valoracion = models.BooleanField(default=False)
and the class for the Favorites (This is working fine yet)
class Favorito(models.Model):
date = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='favoritos')
I have this 'query' in Django.
vines = Vine.custom_object.filter(estado=2).\
annotate(favoritosCount=Count('favoritos', distinct=True)).\
filter(voto__valoracion=False).annotate(disLikesCount=Count('voto', distinct=True))\
.annotate(likesCount=Count('voto', distinct=True)).filter(voto__valoracion=True)
But the second filter is not working because of the first.
Basically what I want is to get the sum of 'positive votes' - 'negative votes' as a field and order by it.
Could anyone please help me?
Thank you in advance
AFAIK you can't do that query with the ORM. You might be able to do it with a raw query.
I think It's easier if you add a count field to your Vine model and order by it. Then update that count field every time there's a new Voto.
Something like this:
from django.db.models import F
class Vine(models.Model):
...
votos = models.IntegerField()
class Meta:
ordering = ('votos',)
class Voto(models.Model):
...
def save(self):
"""When saving new Voto instance, update related Vine."""
if not self.pk:
new_vote = 1 if self.valoracion else -1
self.vine.update(votos=F('votos') + new_vote)
return super(Voto, self).save()
PS: If you want to know more about that F expression.
I'd like to create a filter-sort mixin for following values and models:
class Course(models.Model):
title = models.CharField(max_length=70)
description = models.TextField()
max_students = models.IntegerField()
min_students = models.IntegerField()
is_live = models.BooleanField(default=False)
is_deleted = models.BooleanField(default=False)
teacher = models.ForeignKey(User)
class Session(models.Model):
course = models.ForeignKey(Course)
title = models.CharField(max_length=50)
description = models.TextField(max_length=1000, default='')
date_from = models.DateField()
date_to = models.DateField()
time_from = models.TimeField()
time_to = models.TimeField()
class CourseSignup(models.Model):
course = models.ForeignKey(Course)
student = models.ForeignKey(User)
enrollment_date = models.DateTimeField(auto_now=True)
class TeacherRating(models.Model):
course = models.ForeignKey(Course)
teacher = models.ForeignKey(User)
rated_by = models.ForeignKey(User)
rating = models.IntegerField(default=0)
comment = models.CharField(max_length=300, default='')
A Course could be 'Discrete mathematics 1'
Session are individual classes related to a Course (e.g. 1. Introduction, 2. Chapter I, 3 Final Exam etc.) combined with a date/time
CourseSignup is the "enrollment" of a student
TeacherRating keeps track of a student's rating for a teacher (after course completion)
I'd like to implement following functions
Sort (asc, desc) by Date (earliest Session.date_from), Course.Name
Filter by: Date (earliest Session.date_from and last Session.date_to), Average TeacherRating (e.g. minimum value = 3), CourseSignups (e.g. minimum 5 users signed up)
(these options are passed via a GET parameters, e.g. sort=date_ascending&f_min_date=10.10.12&...)
How would you create a function for that?
I've tried using
denormalization (just added a field to Course for the required filter/sort criterias and updated it whenever changes happened), but I'm not very satisfied with it (e.g. needs lots of update after each TeacherRating).
ForeignKey Queries (Course.objects.filter(session__date_from=xxx)), but I might run into performance issues later on..
Thanks for any tipp!
In addition to using the Q object for advanced AND/OR queries, get familiar with reverse lookups.
When Django creates reverse lookups for foreign key relationships. In your case you can get all Sessions belonging to a Course, one of two ways, each of which can be filtered.
c = Course.objects.get(id=1)
sessions = Session.objects.filter(course__id=c.id) # First way, forward lookup.
sessions = c.session_set.all() # Second way using the reverse lookup session_set added to Course object.
You'll also want to familiarize with annotate() and aggregate(), these allow you you to calculate fields and order/filter on the results. For example, Count, Sum, Avg, Min, Max, etc.
courses_with_at_least_five_students = Course.objects.annotate(
num_students=Count('coursesignup_set__all')
).order_by(
'-num_students'
).filter(
num_students__gte=5
)
course_earliest_session_within_last_240_days_with_avg_teacher_rating_below_4 = Course.objects.annotate(
min_session_date_from = Min('session_set__all')
).annotate(
avg_teacher_rating = Avg('teacherrating_set__all')
).order_by(
'min_session_date_from',
'-avg_teacher_rating'
).filter(
min_session_date_from__gte=datetime.now() - datetime.timedelta(days=240)
avg_teacher_rating__lte=4
)
The Q is used to allow you to make logical AND and logical OR in the queries.
I recommend you take a look at complex lookups: https://docs.djangoproject.com/en/1.5/topics/db/queries/#complex-lookups-with-q-objects
The following query might not work in your case (what does the teacher model look like?), but I hope it serves as an indication of how to use the complex lookup.
from django.db.models import Q
Course.objects.filter(Q(session__date__range=(start,end)) &
Q(teacher__rating__gt=3))
Unless absolutely necessary I'd indeed steer away from denormalization.
Your sort question wasn't entirely clear to me. Would you like to display Courses, filtered by date_from, and sort it by Date, Name?