Any existing solution to implement "opening hours" in Django - django

I'm making a website for a client who wants to be able to change then opening hours
for each of his different stores. Is there an existing solution for this type of problem with Django ?

What do you mean? Seems pretty simple. Adjust according to your weekday order. And if you like, add validation. But people should be smart enough to not need validation for that sort of stuff.
HOUR_OF_DAY_24 = [(i,i) for i in range(1,25)]
WEEKDAYS = [
(1, _("Monday")),
(2, _("Tuesday")),
(3, _("Wednesday")),
(4, _("Thursday")),
(5, _("Friday")),
(6, _("Saturday")),
(7, _("Sunday")),
]
class OpeningHours(models.Model):
store = models.ForeignKey("StoreModel")
weekday_from = models.PositiveSmallIntegerField(choices=WEEKDAYS, unique=True)
weekday_to = models.PositiveSmallIntegerField(choices=WEEKDAYS)
from_hour = models.PositiveSmallIntegerField(choices=HOUR_OF_DAY_24)
to_hour = models.PositiveSmallIntegerField(choices=HOUR_OF_DAY_24)
def get_weekday_from_display(self):
return WEEKDAYS[self.weekday_from]
def get_weekday_to_display(self):
return WEEKDAYS[self.weekday_to]
class SpecialDays(models.Model):
holiday_date = models.DateField()
closed = models.BooleanField(default=True)
from_hour = models.PositiveSmallIntegerField(choices=HOUR_OF_DAY_24, null=True, blank=True)
to_hour = models.PositiveSmallIntegerField(choices=HOUR_OF_DAY_24, null=True, blank=True)

Related

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)

How can I calculate avg of data from django form and store in variable for later use?

In the readerpage function, in my views.py, I am trying to calculate the avg of the two variables: readability_rating and actionability_rating, and store the result in avg_rating
def readerpage(request, content_id):
content = get_object_or_404(Content, pk=content_id)
form = ReviewForm(request.POST)
if form.is_valid():
review = form.save(commit=False)
review.content = content
readability_rating = form.cleaned_data['readability_rating']
readability = form.cleaned_data['readability']
actionability_rating = form.cleaned_data['actionability_rating']
actionability = form.cleaned_data['actionability']
general_comments = form.cleaned_data['general_comments']
review.avg_rating = (float(readability_rating) +
float(actionability_rating)) / 2
review.save()
return redirect('home')
args = {'content': content, 'form': form}
return render(request, 'content/readerpage.html', args)
The problem is that with this setup the two variables are still ChoiceFields - as such the above setup gives me the error:
float() argument must be a string or a number, not 'ChoiceField'
I’ve tried converting them to floats without any luck.
I also attempted using the TypedChoiceField with coerce=float, still with no luck
I’m not sure whether the best place to calculate this is in my function, my form, or my model?
models.py:
class Review(models.Model):
content = models.ForeignKey(Content, null=True, on_delete=models.CASCADE)
readability = models.CharField(null=True, max_length=500)
readability_rating = models.IntegerField(null=True)
actionability = models.CharField(null=True, max_length=500)
actionability_rating = models.IntegerField(null=True)
general_comments = models.CharField(null=True, max_length=500)
avg_rating = models.FloatField(null=True)
def _str_(self):
return self.title
forms.py:
class ReviewForm(forms.ModelForm):
readability = forms.CharField(widget=forms.Textarea)
readability_rating = forms.ChoiceField(
choices=[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)])
actionability = forms.CharField(widget=forms.Textarea)
actionability_rating = forms.ChoiceField(
choices=[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)])
general_comments = forms.CharField(widget=forms.Textarea)
class Meta:
model = Review
fields = ['readability', 'readability_rating',
'actionability', 'actionability_rating', 'general_comments']
Thanks for reading this.
The variables are ChoiceFields because you are declaring them as ChoiceFields in view function. Shouldn't you just fetch the values from your cleaned_data?
readability_rating = form.cleaned_data['readability_rating']
And to the second part of your question: Why not add it as a #property to your model?

Display forms choice in template-Django

On the template, when I call person.health_issue, I am getting '1','2' instead of 'Abdominal pain','Anaphylaxis'. How to display the value ('Abdominal pain','Anaphylaxis') instead of the code(1 or2 etc).
I tried with this also {{ person.get_health_issue_display }} in template,it is not displayed anything.
forms.py
HEALTH_USSUES = (
('1', 'Abdominal pain'), ('2', 'Anaphylaxis'), ('3', 'Asthma'),
('4', 'Bruising'), ('5', 'Chest pains'), ('6', 'Coughs or Colds')
)
class PersonActionsForm(forms.ModelForm):
action = forms.MultipleChoiceField(widget=forms.Select(), choices=HEALTH_USSUES, required=False)
models.py
class ReportPerson(models.Model):
report = models.ForeignKey(Report)
name = models.CharField('Name', max_length=100)
first_aid = models.BooleanField('First aid', default=False)
health_issue = models.IntegerField(default=0)
views.py
def report_template(request):
""""""
person = ReportPerson.objects.get(pk=person_id)
""""""
return render(request, 'event/print.html',
{
'person':person
})
can any one tell me how to do this.
Thanks
As you don't have any choices set in model field health_issue you need to write the get_health_issue_display method by your self i will name it as health_issue_display so that default get_FOO_display method not gets overridden:
HEALTH_USSUES = (
(1, 'Abdominal pain'), (2, 'Anaphylaxis'), (3, 'Asthma'),
(4, 'Bruising'), (5, 'Chest pains'), (6, 'Coughs or Colds')
)
class ReportPerson(models.Model):
report = models.ForeignKey(Report)
name = models.CharField('Name', max_length=100)
first_aid = models.BooleanField('First aid', default=False)
health_issue = models.IntegerField(default=1)
def health_issue_display(self):
for c in HEALTH_USSUES:
if c[0] == self.health_issue:
return c[1]
Or just add choices in the model field:
health_issue = models.IntegerField(default=1, choices=HEALTH_USSUES)
Now you have get_health_issue_display.
Also make the first value in every choice as integer (1, 'Abdominal pain') rather than string '1'. Just to remove the confusion.
You have default=0 which does not exists in choices. Change it to default=1

Django - Objects for business hours

I'm trying to modelize business hours for a week of a company. Here is my attempt:
class Company(models.Model):
name = models.CharField(max_length=100)
logo = models.FileField(upload_to='company_logos')
mon_start = models.TimeField()
mon_end = models.TimeField()
tue_start = models.TimeField()
tue_end = models.TimeField()
wed_start = models.TimeField()
wed_end = models.TimeField()
thu_start = models.TimeField()
thu_end = models.TimeField()
fri_start = models.TimeField()
fri_end = models.TimeField()
sat_start = models.TimeField()
sat_end = models.TimeField()
sun_start = models.TimeField(blank=True)
sun_end = models.TimeField(blank=True)
Does this seem correct ?
Isn't there a more dynamic way to define it ?
Can I easily validate each day (on a form) ?
From #lyapun suggestion, an acceptable solution for me would be:
WEEKDAYS = [
(1, _("Monday")),
(2, _("Tuesday")),
(3, _("Wednesday")),
(4, _("Thursday")),
(5, _("Friday")),
(6, _("Saturday")),
(7, _("Sunday")),
]
class Company(models.Model):
name = models.CharField(
max_length=100
)
logo = models.FileField(
upload_to='company_logos'
)
class OpeningHours(models.Model):
store = models.ForeignKey(
Company
)
weekday = models.IntegerField(
choices=WEEKDAYS,
unique=True
)
from_hour = models.TimeField()
to_hour = models.TimeField()

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]