Filter Creation Date By Time Range - django

Im trying to filter my first two IF statement to only show the created_at records from 8 am to 10 am for todays current date, right now it just does the date, i need change date= date to created_at = '' however that would be done in a range. Here is my views.py. How do i add this to my IF statement ? Thanks
views.py
def Student_Progress(request, studentpsid):
if request.method == "GET":
date = datetime.date.today()
# Calculates Points on Student Progress Page
academic = K8Points.objects.values_list('academic', flat=True).filter(
student_name_id=studentpsid).filter(date=date)
behavior = K8Points.objects.values_list('behavior', flat=True).filter(
student_name_id=studentpsid).filter(date=date)
my_class_id = request.session['my_class_id']
academic_total = 0
behav_total = 0
for score in academic:
academic_total += int(score)
for score in behavior:
behav_total += int(score)
grand_total = academic_total + behav_total
counseling = Student.objects.values_list(
'counseling_goal', flat=True).get(studentpsid=studentpsid)
studentid = Student.objects.get(studentpsid=studentpsid)
k8obj = K8Points.objects.filter(
student_name_id=studentpsid, date=date).order_by('time_frame')
# Checks To See If a Student Gets Morning Recess
if grand_total >= 20 and K8Points.objects.filter(time_frame=1).filter(date=date) and K8Points.objects.filter(time_frame=2).filter(date=date) and K8Points.objects.filter(time_frame=3).filter(date=date):
morning_recess = "YES"
context = ({'studentid': studentid, 'date': date, 'counseling': counseling, 'grand_total': grand_total, 'academic_total': academic_total,
'behav_total': behav_total, 'k8obj': k8obj, 'my_class_id': my_class_id, 'morning_recess': morning_recess})
return render(request, 'points/student_progress.html', context)
if grand_total <= 20 and K8Points.objects.filter(time_frame=1) and K8Points.objects.filter(time_frame=2) and K8Points.objects.filter(time_frame=3).filter(date=date):
morning_recess = "NO"
context = ({'studentid': studentid, 'date': date, 'counseling': counseling, 'grand_total': grand_total, 'academic_total': academic_total,
'behav_total': behav_total, 'k8obj': k8obj, 'my_class_id': my_class_id, 'morning_recess': morning_recess})
return render(request, 'points/student_progress.html', context)
else:
context = ({'studentid': studentid, 'date': date, 'counseling': counseling, 'grand_total': grand_total, 'academic_total': academic_total,
'behav_total': behav_total, 'k8obj': k8obj, 'my_class_id': my_class_id, })
return render(request, 'points/student_progress.html', context)
models.py
class K8Points(models.Model):
date = models.DateField(default=datetime.date.today())
class_name = models.ForeignKey(TeacherClass, on_delete = models.PROTECT, default = "",)
student_name = models.ForeignKey(Student,on_delete = models.CASCADE, default ="" ,)
week_of = models.IntegerField(default=weeknumber)
day = models.CharField(max_length= 10, default = dayofweek)
TIME_FRAME_CHOICES = [
(None, 'PLEASE SELECT TIME FRAME'), # THIS IS OPTIONAL
(1, '(1.) 8:45AM - 9:00AM'),
(2, '(2.) 9:00AM - 9:30AM'),
(3, '(3.) 9:30AM - 10:00AM'),
(4, '(4.) REC. I 10:00AM -10:10AM'),
(5, '(5.) 10:10AM-10:40AM'),
(6, '(6.) 10:40AM-11:10AM'),
(7, '(7.) 11:10AM-11:40AM'),
(8, '(8.) REC II LUNCH 11:40AM-12:20PM'),
(9, '(9.) 12:20PM-12:50PM'),
(10,'(10.) 12:50PM-1:20PM'),
(11,'(11.) 1:20PM-1:50PM'),
(12,'(12.) 1:50PM-2:20PM'),
(13,'(13.) REC. III 2:20PM-2:30PM'),
]
time_frame = models.PositiveSmallIntegerField(choices=TIME_FRAME_CHOICES,)
behavior = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(1)
])
academic = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(0)
] )
total = models.IntegerField(default=0 )
morning_recess= models.CharField(max_length= 3, blank = True ,default = "" )
created_at = models.DateTimeField(auto_now_add=True)

for today day filter
today_date = datetime.datetime.now().date()
.filter(your_datetime_field__date = today_date)
for hour filter
.filter(your_datetime_field__hour__lte = 10).filter(your_datetime_field__hour__gte = 8)
Keep in mind that 10:59:59 will be in results of this query too.
If you need only 8:00:00 - 9:59:59 use lt instead of lte

Related

Filter Foreign Key Drop Down Field Django

I have 3 tables Student, K8Points, and TeacherClass . The table students tracks all student data information and you can assign them to a classroom, points tracks the points they earned for the day, classroom table is where you create the classroom names. What i want to accomplish is when you are logged in to /k8_points_classroom/1? page, there is a drop down field of students. 1 at the end of the classroom is the classroom id. The field student_name should only show the kids in that particular class, how do i filter that field ? Right now it just pulls up every student in the database. Thanks for the help .
Model
class TeacherClass(models.Model):
class_name = models.CharField(max_length = 50, default= "")
teacher_name = models.ManyToManyField(User)
grade = models.CharField(max_length = 2, default= "")
class Meta:
verbose_name = "Teacher Class Room"
def __str__(self):
return self.class_name
class Student(models.Model):
studentpsid= models.CharField(primary_key = True , default = "", max_length = 50, unique = True)
student_name = models.CharField(max_length = 50)
student_grade = models.CharField(max_length = 2, default = "")
home_room = models.CharField(max_length = 3, default = "")
counseling_goal = models.TextField(max_length = 255)
class_name = models.ManyToManyField(TeacherClass)
image =models.ImageField(default ="default.png", upload_to='student_pics')
class K8Points(models.Model):
date = models.DateField(default=datetime.date.today)
class_name = models.ForeignKey(TeacherClass, on_delete = models.PROTECT, default = "",)
student_name = models.ForeignKey(Student,on_delete = models.CASCADE, default ="" ,)
week_of = models.IntegerField(default=weeknumber)
day = models.CharField(max_length= 10, default = dayofweek)
TIME_FRAME_CHOICES = [
(None, 'PLEASE SELECT TIME FRAME'),
(1, '(1.) 8:45AM - 9:00AM'),
(2, '(2.) 9:00AM - 9:30AM'),
(3, '(3.) 9:30AM - 10:00AM'),
(4, '(4.) REC. I 10:00AM -10:10AM'),
(5, '(5.) 10:10AM-10:40AM'),
(6, '(6.) 10:40AM-11:10AM'),
(7, '(7.) 11:10AM-11:40AM'),
(8, '(8.) LUNCH 11:40AM-12:00PM'),
(9, '(9.) REC. II 12:00PM-12:20PM'),
(10, '(10.) 12:20PM-12:50PM'),
(11,'(11.) 12:50PM-1:20PM'),
(12,'(12.) 1:20PM-1:50PM'),
(13,'(13.) 1:50PM-2:20PM'),
(14,'(14.) REC. III 2:20PM-2:30PM'),
]
time_frame = models.PositiveSmallIntegerField(choices=TIME_FRAME_CHOICES,)
behavior = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(1)
])
academic = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(0)
] )
created_at = models.DateTimeField(default = timezone.now)
class Meta:
verbose_name = "K8-Points"
def __str__(self):
return self.student_name
Form
def __init__(self, *args, **kwargs):
self.classid = kwargs.pop('classid', None)
super(K8Points_ClassroomForm,self).__init__(*args,**kwargs)
self.fields['date'].disabled = True
self.fields['day'].disabled = True
self.fields['week_of'].disabled = True
self.fields['class_name'].widget.attrs['readonly'] = True
getstudents = Student.objects.filter(class_name = self.classid).order_by('student_name')
self.fields['student_name'].queryset= getstudents.all().order_by('student_name')
View
#login_required
def K8_Points_Classroom(request, classid):
if request.method == "GET":
date = datetime.date.today()
students = Student.objects.filter(class_name=classid).order_by('student_name')
class_name = TeacherClass.objects.get(id=classid)
form = K8Points_ClassroomForm(classid = class_name.id)
request.session['my_class_id'] = classid
return render(request, 'points/k8_points_classroom.html', {'form': form, 'students': students, 'class_name': class_name, 'date': date , 'classid': classid})
You need to pass the class in as a parameter to the form in the view, then adjust the student_name field's queryset to filter down to that class' students.
class K8PointsClassroomForm(forms.ModelForm):
def __init__(self, *args, class_=None, **kwargs):
super (K8Points_ClassroomForm,self).__init__(*args,**kwargs )
self.fields['date'].disabled = True
self.fields['day'].disabled = True
self.fields['week_of'].disabled = True
# Limit the fields queryset to that of the class's students.
self.fields['student_name'].queryset = class_.student_set.all()
Edit:
Here's the view I was trying to explain:
#login_required
def K8_Points_Classroom(request, classid):
class_name = TeacherClass.objects.get(id=classid)
form = K8Points_ClassroomForm(class_=class_name)

Combine Two Variable Filters Django

I have two filters in my code here, students filters everyone in that particular class and students_wr is another filter that quieres my table K8Recess which logs all the students in the school who got recess for that day. What I want to do is combine these filters.
So show everyone in my class who got recess for the day . How do i do that ? Here is my Code
def K8_Recess_Report(request, classid):
if request.method == "GET":
date = datetime.date.today()
class_name = TeacherClass.objects.get(id=classid)
getstudents = Student.objects.filter(class_name=classid)
students = getstudents.all().order_by('student_name')
students_wr = K8Recess.objects.filter(created_at__date = date )
my_class_id = request.session['my_class_id']
context = ({'students': students, 'class_name': class_name, 'my_class_id': my_class_id, 'date': date,})
return render(request, 'points/k8_recess_report.html', context)
class K8Points(models.Model):
date = models.DateField(default=datetime.date.today())
class_name = models.ForeignKey(TeacherClass, on_delete = models.PROTECT, default = "",)
student_name = models.ForeignKey(Student,on_delete = models.CASCADE, default ="" ,)
week_of = models.IntegerField(default=weeknumber)
day = models.CharField(max_length= 10, default = dayofweek)
TIME_FRAME_CHOICES = [
(None, 'PLEASE SELECT TIME FRAME'), # THIS IS OPTIONAL
(1, '(1.) 8:45AM - 9:00AM'),
(2, '(2.) 9:00AM - 9:30AM'),
(3, '(3.) 9:30AM - 10:00AM'),
(4, '(4.) REC. I 10:00AM -10:10AM'),
(5, '(5.) 10:10AM-10:40AM'),
(6, '(6.) 10:40AM-11:10AM'),
(7, '(7.) 11:10AM-11:40AM'),
(8, '(8.) LUNCH 11:40AM-12:00PM'),
(9, '(9.) REC. II 12:00PM-12:20PM'),
(10, '(10.) 12:20PM-12:50PM'),
(11,'(11.) 12:50PM-1:20PM'),
(12,'(12.) 1:20PM-1:50PM'),
(13,'(13.) 1:50PM-2:20PM'),
(14,'(14.) REC. III 2:20PM-2:30PM'),
]
time_frame = models.PositiveSmallIntegerField(choices=TIME_FRAME_CHOICES,)
behavior = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(1)
])
academic = models.IntegerField(default="", validators=[
MaxValueValidator(5),
MinValueValidator(0)
] )
created_at = models.DateTimeField(default=datetime.datetime.now())
class Meta:
verbose_name = "K8-Points"
def __str__(self):
return self.student_name
class K8Recess(models.Model):
student_ps = models.ForeignKey(Student,on_delete = models.CASCADE, default ="" ,)
created_at = models.DateTimeField(default=datetime.datetime.now())
morning_recess = models.BooleanField(blank= True, null = True)
lunch_recess = models.BooleanField(blank= True, null = True)
afternoon_recess = models.BooleanField(blank= True, null = True)
You can get this by:
K8Recess.objects.filter(student_ps__class_name=classid, created_at__date=date)

Django foreign key backreference filter results

I have a model as follows:
class Event(models.Model):
name = models.CharField(max_length=50, blank=False, verbose_name="Event name", )
date = models.DateField(auto_now=False, auto_now_add=False, )
hall = models.ForeignKey(Hall, on_delete=models.CASCADE, null=True, related_name='events', )
I have a view just for trying out results:
#api_view(('GET',))
def get_specific_hall(request, cityId, year = None, month = None, day = None):
hall = Hall.objects.filter(city=cityId)
testHall = Hall.objects.get(city=cityId)
date = year + '-' + month + '-' + day
events = []
for event in testHall.events.filter(~Q(date=date)):
events.append(event)
eventSerializer = EventSerializer(events, many=True)
serializer = HallSerializer(hall, many=True)
return Response(serializer.data + eventSerializer.data)
What I want is: I am passing date as a url parameter. I want to return those Hall objects from a specific city and which do not have any associated event for that date. i.e. only available hall.
How can I achieve that?
I updated my view as follows:
#api_view(('GET',))
def get_specific_halls(request, cityId, year = None, month = None, day = None):
date = year + '-' + month + '-' + day
hall = Hall.objects.all().filter(Q (city=cityId) , ~Q(events__date=date))
serializer = HallSerializer(hall, many=True)
return Response(serializer.data)

Allow user to sign up only for shifts that are not yet claimed?

I have a table of shifts for meals:
class mealShifts(models.Model):
Sunday = "Sunday"
Monday = "Monday"
Tuesday = "Tuesday"
Wednesday = "Wednesday"
Thursday = "Thursday"
Friday = "Friday"
Days = (
(0, "Sunday"),
(1, "Monday"),
(2, "Tuesday"),
(3, "Wednesday"),
(4, "Thursday"),
(5, "Friday"),
(6, "Saturday")
)
Breakfast = "Breakfast"
Dinner = "Dinner"
Meals = (
(Breakfast, "Breakfast"),
(Dinner, "Dinner"),
)
Chef = "Chef"
Sous_Chef = "Sous-Chef"
KP ="KP"
Shifts = (
(Chef, "Chef"),
(Sous_Chef, "Sous_Chef"),
(KP, "KP"),
)
assigned = models.BooleanField(default=False)
day = models.CharField(max_length = 1, choices=Days)
meal = models.CharField(max_length = 10, choices=Meals)
shift = models.CharField(max_length = 10, choices=Shifts, default=KP)
camper = models.OneToOneField(User)
class Meta:
unique_together = ("day", "meal", "shift")
def __str__(self):
return '%s %s %s %s'%(self.day, self.meal, self.shift, self.camper)
And here is my view:
#login_required(login_url='login.html')
def signup(request):
sundayShifts = mealShifts.objects.filter(day="Sunday")
mondayShifts = mealShifts.objects.filter(day="Monday")
#the rest of the shifts will go here
username = None
context = RequestContext(request)
if request.method == 'POST':
form = MealForm(request.POST)
if form.is_valid():
shift = form.save(commit=False)
shift.camper = request.user
shift.save()
return redirect('signup')
else:
print form.errors
else:
form = MealForm()
return render_to_response('signup.html',
RequestContext(request, {'form':form,'username':username, 'sundayShifts':sundayShifts, 'mondayShifts':mondayShifts},))
There are 42 possible meal shifts. How can I create a view that will display only the shift choices that nobody has taken - the possible combinations which aren't yet in the database?
You could do something like:
import itertools
# Ideally, reuse these from the model some how
day_choices = range(0, 6)
meal_choices = [Breakfast, Dinner]
shift_choices = [Chef, Sous_Chef, KP]
shift_options = itertools.product(day_choices, meal_choices, shift_choices)
avaliable_shift_choices = filter(
lambda option: not mealShifts.objects.filter(day=options[0], meal=option[1], shift=option[2]).exists(),
shift_options
)
This will give you combinations of day, meal and shift not currently in the db, without loading too much data, or being too expensive on the db.

How do I get the top-ranked products within a category?

Given a product (product_name is a parameter in the view), I am trying to return the 5 top-ranked products within that category (as defined by the method "get_avg_rating") as a list that I can loop through in a template. Any advice on how to do this?
class Productbackup(models.Model):
website = models.CharField('Product name', max_length = 200)
url_friendly = models.CharField('URL friendly', max_length = 200)
website_url = models.URLField('Product URL')
description= models.CharField('Description', max_length = 2000)
category = models.ForeignKey(Categories)
#category = models.ManyToManyField(Categories)
image_hero = models.URLField('Hero image url')
image_second = models.URLField('Second image url')
image_third = models.URLField('Third image url')
created_on = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
def __unicode__(self):
return self.website
def get_avg_rating(self):
reviews = Reviewbackup.objects.filter(product=self)
count = len(reviews)
sum = 0.0
for rvw in reviews:
sum += rvw.rating
return (sum/count)
def get_num_reviews(self):
reviews = Reviewbackup.objects.filter(product=self)
count = len(reviews)
return count
RATING_OPTIONS = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5'),
(6, '6'),
(7, '7'),
(8, '8'),
(9, '9'),
(10, '10'),
)
class Reviewbackup(models.Model):
review = models.CharField('Review', max_length = 2000)
created_on = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(auto_now = True)
user = models.CharField('Username', max_length = 200)
rating = models.IntegerField(max_length=2, choices=RATING_OPTIONS)
product = models.ForeignKey(Productbackup)
def __unicode__(self):
return self.review
class Categories(models.Model):
category = models.CharField('Category_second', max_length = 200)
url_friendly = models.CharField('url_friendly', max_length = 200)
def __unicode__(self):
return unicode(self.category)
def view_reviews(request, product_name):
product = get_object_or_404(Productbackup, url_friendly=product_name)
product_id = product.id
#get reviews for the this product
reviews = Reviewbackup.objects.filter(product_id=product_id).order_by("-created_on")
#similar products in category comparison
prod_category = Productbackup.objects.filter(category=product.category)
#top_ranked = Productbackup.objects.order_by('get_avg_rating')[0:5]
#recently added
recent_added = Productbackup.objects.order_by('-created_on')[0:5]
return render_to_response('reserve/templates/view_reviews.html', {'prod_category': prod_category, 'product':product, 'reviews':reviews, 'recent_added':recent_added},
context_instance=RequestContext(request))
You can use annotate for that
from django.db.models import Sum, Avg
def get_top_products(amount=5):
try:
Productbackup.objects.annotate(review_amount=Sum("reviewbackup__product")).\
order_by("review_amount")[:amount]
except Productbackup.DoesNotExist:
return None
This is just a basic example, which can be extended to your needs
Try to implement that:
Create a dictionary. It will have the Product as the key and the rating as the value.
Loop through your items (Product.objects)
In that loop, put each item in the dictionary
Out of that loop, sort the dictionary by value.
(See Sort a Python dictionary by value)
Get the last items of the dictionary (dictionary[-5]).
Note that you will have to handle items with ex-aequo ratings. Indeed, if 10 items have the same score, then your Top 5 doesn't mean anything using the above method.
This would result in a code similar to this:
items_with_rating = {}
for product in Product.objects:
items_with_rating[product] = product.get_avg_rating()
items_sorted_by_rating = sorted(items_with_rating.iteritems(), key=operator.itemgetter(1))
top5_items = items_sorted_by_rating[-5]
Maybe something like this could work?
products = [[prod, prod.get_avg_rating()] for prod in Productbackup.objects()]
top_5_items = sorted(products, key=lambda x: x[1], reverse=True)[:5]