How to make a reservation system in django - django

I am making a delivery date and time reservation system in django and there I need to implement a reservation system of time and date for the users.
see this UI image here for better understanding
I have to make such a kind of thing that if a user reserves a specific time lets say 9 AM on a specific date and places an order, then that particular time related to that particular date that the user placed an order on will get disabled so that no other user can place an order on that same date and time.
Now, the problem is I am not very sure how to design the database relationships for this feature.
Initially I'm thinking of this model design bellow but I'm sure that it's not that much efficient.
class Date(models.Model):
date = models.DateField()
class Time(models.Model):
time = models.TimeField(auto_now=False, auto_add_now=False)
date = models.ForeignKey('Date', on_delete=models.CASCADE)
Let's assume that one of my users placed an order on 3rd of the month with a delivery time of 10 AM. So according to the system the time '10 AM' on 3rd of the month should get disabled for other users. But the time '10 AM' on other days of the month should still remain open for an order to be placed on.
I don't understand how to do this whole thing with model relationships.
Any help from you guys would be very beneficial for me. Please consider helping me with as much idea as you can.
Thanks.

You can place the time of the order in the order model itself. By setting unique=True you make sure that a specific time is only existing once in the database.
class Order(models.Model):
order_time = models.DateTimeField(null=False, blank=False, unique=True)
You can check if an order with a specific date is already existing by using get
try:
order_exists = Order.objects.get(order_time=time_to_check)
except Order.DoesNotExist:
print('The order is not existing!')

Related

Should I create a model to contain another model instances? (Django)

I'm new to django so I'm not sure of the proper way to do things (or the convention).
Say I want to make a project which contains my everyday notes.
I'm going to create multiple notes every day (where each note is going to be an instance of a "Note" model).
I want in my project-frontend to have containers, where I start with containers, each of a specific year (say 2020, 2021, ...) and each of these containers contains month containers (Jan, Feb, ...) and each of those contains day containers (1, 2, ..) and each of those contains the notes of this specific day.
Now my question is should, in my backend, make a NoteYear model which has instances of a NoteMonth model which has instances of NoteDay model which has instances of Note model?
I understand that I can filter the objects by the DateTimeField, and put them in different containers in the frontend (Of course I'll have a DateTimeField for each Note instance anyways).
The reason I thought of this is because it should be faster filtering to get to a specific day.
I'd love to hear your opinions!
Models should not be written based on how to present data at the front-end. Models should try to represent and store data in an effective manner.
Here it would be pure fabrication to create models for the year, month and day items. A simple Note model with a DateTimeField should suffice, especially if you add a database index to that field such that it can easily filter.
Such model thus looks like:
from django.db import models
class Note(models.Model):
note = models.TextField()
created = models.DateTimeField(auto_now_add=True, db_index=True)
You can then effectively retrieve items for a given year, month, day with:
Note.objects.filter(created__year=2021) # year
Note.objects.filter(created__year=2021, created__month=9) # month
Note.objects.filter(created__year=2021, created__month=9, day=25) # day
You may use models as storage objects which means you don't have to define your models based on each and every container.
Accordingly, you may define you models as follows and use django-template to iterate and filter by dates into years/months/days.
class Notes(models.Model):
title = models.CharField(max_length=200)
created = models.DateTimeField(default=timezone.now)
updated = models.DateTimeField(default=timezone.now, blank=True)

How to structure django models and query them with ease?

I am building a Django web App that will count the total number of persons entering and exiting a school library in a day, week and year and then save to DB.
The Web App uses a camera that is controlled by OpenCv to show live feed on frontend (I have successfully implemented this already).
My problem is:
How can I design and structure my models to store each data by day, week, month and year?
And how can I query them to display them on different Bar Charts using chart.js?
I haven't used chart.js before but I think I can answer the first part of your question.
Consider this model from one of my projects for a "post" that a user can make on my webapp.
class Post(models.Model):
slug = models.SlugField(unique=True)
title = models.CharField(max_length=100)
description = models.CharField(max_length=2200)
image = models.ImageField(upload_to=photo_path, blank=False, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
Using a "DateTimeField" (or alternatively a "DateField") you can pretty easily store timestamp information which can be filtered using standard python Date or DateTime object comparisons. In my example, I'm storing image files and text information.
For your case you could simply create a new "Person" model where each person is given a timestamp (and whatever other info you might want to store) and then using django querying you can count how many people match certain datetime parameters.
Note the Django Docs (https://docs.djangoproject.com/en/3.1/ref/models/querysets/) recommend :
Don't use len() on QuerySets if all you want to do is determine the number of records in the set. It's much more efficient to handle a count at the database level, using SQL's SELECT COUNT(*), and Django provides a count() method for precisely this reason.
An example of how I'd approach your problem would be:
Models:
class Person(HabitModel):
timestamp = models.DateTimeField(auto_now_add=True)
#whatever extra data you want on each person walking by
#staticmethod
def get_number_of_people(start_timestamp, end_timestamp):
return Person.objects.filter(timestamp__gte=start_timestamp, timestamp__lt=end_timestamp)).count()
(Note the "__gte" and "__lt" are built-in for Django querying and imply [start_timestamp, end_timestamp) inclusive start time and exclusive endtime)
Now you should be able to store your data rather simply and quantify how many people objects were created in whatever timeframe you'd like!

Resetting table values through DateTime in Django

I am attempting to create a voting database with an increasing number of names that are never deleted or reset. Votes are cast in the morning, and voting is closed around 10:00. I want to have a separate view that resets the votes back to zero for each instance in the afternoon, after the process is over. How might I accomplish this? Will I have to manually visit this view every day or can it be automated with a DateTime field as the parameter? I have a model to archive old results, but I want to re-use the voting models every day.
class restuarant(models.Model):
name = models.CharField(max_length=50)
votes = models.IntegerField()
percent = models.DecimalField(max_digits=23, decimal_places=20)
def __unicode__(self):
return self.name
class totalVotes(models.Model):
total = models.IntegerField()
class restuarantVote(models.Model):
#voting model for statistic information
choice = models.CharField(max_length=50)
totalVotes = models.IntegerField()
created = models.DateField()
def __unicode__(self):
return self.choice
as andrew suggested resetting data might not be the best approach.
Storing just the raw vote could provide a number of benefits:
you wouldn't have to worry about resetting the data each day. (which could require a cron job to update)
you could analize the data in any way you want.
it is more extendable. You can build more flexible system, suppose you want to add user to the vote to track what a particular user likes?
That way you can see the vote for ANY day not just the current day. You could change up your model:
class Vote(models.Model):
choice = models.CharField(max_length=50)
created = models.DateField(auto_now_add=True)
throughout the day you could just add a vote when one is received
new_vote = Vote(choice=the_choice)
new_vote.save()
then to get the days vote:
todays_count = Vote.objects.filter(choice=the_choice, created=date_obj_here).count()
The best solution to this kind of problem is almost always to eliminate the need for resets entirely. If you can't figure out how to do this conceptually, consider posting more details on your model and application and what you mean by "resetting the votes".
If you absolutely need to run some kind of process daily to clean up your database, you can write a python script and import your application's settings and model file, and then run thej python script with cron on the server. There are a few other too-clever solutions, but almost always you should reconsider your design first.
Edit: now that the code has been added to the question: I recommend you make each restaurantVote represent a single vote cast by a unique individual, and remove the totalVotes IntegerField. Create a new restaurantVote object for each vote cast. You can add a datetime or date field to restaurantVote to mark when it was cast. When you want to total votes, do a query to total up the number of votes for each choice between the beginning and the end of a given day, or just for the given day if you are using a date field instead of a datetime field.
If you don't want to do that, you can keep the IntegerField on there but just add the date field. Every time someone votes, look to see if there is a restaurantVote for that choice and the current day already; if not, then create it (you may be able to use get_or_create() for this).
By the way, if restaurantVote is supposed to be a vote cast for an individual restaurant, then you can use a foreignkey relationship instead of a CharField for choice.

Adding ManyToMany extra field to QuerySet in django

Suppose I have following models:
class Thing(models.Model):
name = models.CharField(max_length=100)
ratings = models.ManyToManyField('auth.User', through='Rating')
class Rating(models.Model):
user = models.ForeignKey('auth.User')
thing = models.ForeignKey('Thing')
rating = models.IntegerField()
So I have a lot of things, and every user can rate every thing. I also have a view showing a list of all things (and they are huge in numbers) with a rating that user assigned to each of them. I need a way to retreive all the data from database: Thing objects with additional field user_rating taken from at most one (because we have a fixed User) related Rating object.
Trivial solution looks like that:
things = Thing.objects.all()
for thing in things:
try:
thing.user_rating = thing.ratings.objects.get(user=request.user).rating
except Rating.DoesNotExist:
thing.user_rating = None
But the flaw of this approach is obvious: if we have 500 things, we'll do 501 requests to database. Per one page. Per user. And this is the most viewed page of the site. This task is easily solvable with SQL JOINs but in practice I have more complicated schema and I will certainly benefit from Django model framework. So the question is: is it possible to do this Django-way? It would be really strange if it isn't, considering that such tasks are very common.
As I understood, neither annotate(), nor select_related() will help me here.
I guess you should try this:
https://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra
Example
result = Thing.objects.all().extra(select={'rating': 'select rating from ratings where thing_id = id'})
Your result set gets a new field 'rating' for each 'thing' object.
I use this approach in one of my recent projects. It produces one complex query instead of n+1 queries.
Hope this helps :)
Since you are planning to display everything in one page. I can think of this approach. You can give this a try:
Get all the ratings given by the current user and Get all the Things.
Now try to create a dictionary like this:
thing_dict = {}
for thing in Thing.objects.all():
thing_dict[thing] = None
for rating in Rating.objects.filter(user = request.user):
thing_dict[rating.thing] = rating
Now thing_dict contains all the entries of model Thing as keys and has its rating as its value.
May not be the best way. I am keen on seeing what others answer.

Django: How to keep track of a linear (yet flexible) project management workflow?

I'm developing a project management application in Django that requires a somewhat linear response process involving different groups of users (as in Django auth Groups). Each step in the response process has several response options (most options unique to the step) and is assigned to a user within a particular group. The next step in the process is determined by the user's response, and occasionally additional information may need to be requested from one of the project's members.
The problem is that my current implementation seems rather cumbersome and I am certain there is a better way to keep track of the response process. I was hoping someone could provide some insight into a more robust solution.
As a simple example, consider a Project with the following user Groups: Sales Rep, Sales Manager, and Project Manager. The models currently looks like this:
class Project(models.Model):
assigned_to = models.ForeignKey(User, related_name="projects_assigned_to") #Indicates which user needs to respond next. Will be sales_rep, sales_mgr, or project_mgr.
sales_rep = models.ForeignKey(User, related_name="sales_rep_projects") #choices limited to "Sales Rep" Group
sales_mgr = models.ForeignKey(User, related_name="sales_mgr_projects") #choices limited to "Sales Manager" Group
project_mgr = models.ForeignKey(User, related_name="project_mgr_projects") #choices limited to "Project Manager" Group
current_step = models.ForeignKey(Step, related_name="projects_with_current_step")
previous_step = models.ForeignKey(Step, related_name="projects_with_previous_step")
status = models.ForeignKey(Status) #Automatically assigned according to the user's response. Includes things like "On Track", "On Hold", "Rejected", "Accepted", etc.
class Step(models.Model):
name = models.CharField(max_length=50)
class Status(models.Model):
name = models.CharField(max_length=50)
Here's a simple overview of how the process might work:
Sales Rep creates a new project and it is assigned to Sales Manager
Sales Manager is presented with the following options:
(a) approve the project or
(b) request more information from the Sales Rep
If the project is approved, assign to Project Manager who is presented with the following options:
(a) commence the project
(b) reject the project
(c) request more information from the Sales Rep or Sales Manager
If more information is requested from a user, the project is assigned to that user and they just need to provide a textbox response. However, once their response has been received, the project needs to return to the previous step (this is why I keep track of current_step and previous_step above). In this example, if Project Manager requests more information from the Sales Rep, once the Sales Rep responds the project should be assigned back to the Project Manager with the same response options that he had before (commence, reject, request more information).
The full process has about 10 or so steps like these.
To complicate things, I also need to be able to display the response chosen for each step. For example, if the Sales Manager approves the project, it should display "Sales Manager approved the project" along with any comments they may have. The model looks like this:
class Response(models.Model):
comment = models.TextField()
response_action = models.ForeignKey(ResponseAction)
submitted = models.DateTimeField()
class ResponseAction(models.Model):
""" I.e. 'Sales Manager approved the project', 'Project Manager commenced the project'"""
name = models.CharField(max_length=100)
Right now the logic for each response action is hard coded in the view, and there's no formal relationship between one step and another. I feel like there's a better model structure or data structure I should be using to keep track of this workflow, but I've been working with the current system for so long that I'm having trouble thinking about it differently. Any insight or inspiration would be greatly appreciated! Let me know if I need to clarify anything.
Make more use of the Step model. You can have it hold the possible next steps as foreign keys. This way you can edit the flow by changing data (using the admin for example, instead of hardcoding it). Maybe something like:
class Step(models.Model):
name = models.CharField(max_length=50)
responsible_role = models.CharField(max_length=50) # this contains 'sales_rep', 'sales_mgr' etc
allowed_actions = models.ManyToManyField('AllowedAction')
class AllowedAction(models.Model):
name = models.CharField(max_length=50)
next_step = models.ForeignKey('Step') # the next step, if this action is chosen
Seperate the actual project history to another model:
class ProjectHistoryStep(models.Model):
timestamp = models.DateTimeField()
step = models.ForeignKey('Step')
project = models.ForeignKey('Project')
You can use this model to track the actual progress of your projects (don't forget that models have get_next_by_FOO).
You'll only need 1 view that handles all the logic (it should just call some method on the Project class to do the actual work) - check what state the project is in now (latest ProjectHistoryStep for that project), and what was the User's action, and act accordingly.