I want to develop DJANGO Application for rooms booking.
I want to use following TWO models.
class Room(models.Model):
room_no = models.IntegerField()
remarks = models.CharField(max_length=100)
def __str__(self):
return self.remarks
class Roombooking(models.Model):
room = models.ForeignKey(Room, related_name= 'roombookingforroom', on_delete=models.CASCADE)
booked_for_date = models.DateField(blank=True, null=True)
booked_by = models.TextField(max_length=1000, default='')
remarks = models.CharField(max_length=100,)
class Meta:
constraints = [
models.UniqueConstraint(
fields=["suit", "booked_for_date"],
name="unique_room_date",
),
]
def __str__(self):
return self.room.remarks
To avoid assigning one room to 2 different persons on any day, “ UniqueConstraint” is used.
Now, how to query the list of rooms which are vacant from DATE1 to DATE2
You can just filter the room booking by date
gte = greater than or equal to
lte = lower than or equal to
query = Roombooking.objects.filter(booked_for_date__gte=DATE1, booked_for_date__lte=DATE2)
*Note that DATE1 and DATE2 should be datetime type
You can have a look on official documentation
Related
I'm writing a program to store analyses for patient and I need to make a form with nested forests with next scheme
Each patient has an analyses results sheet
Each result sheet has date, patient (foreign key) and set of analyses values
Each set of analyses values has strict number and strict types of analyses
Each type of analyse has it's value, name and units
For example I want to create John's analyse result sheet for blood
Patient: John Date: 10.02.23
Set of values: 'Blood analysis'
Red blood cells:
3,23 10^9 Haemoglobin: 124 g/l
I've made models:
analysis/models.py
class AnalysisGroup(models.Model):
name = models.CharField(max_length=64)
class AnalysisType(models.Model):
name = models.CharField(max_length=256)
measurement = models.CharField(max_length=10)
analysis_group = models.ForeignKey(AnalysisGroup, on_delete=models.CASCADE)
class PatientAnalysisResultSheet(models.Model):
an_number = models.PositiveBigIntegerField()
date = models.DateField()
time = models.TimeField()
patient = models.ForeignKey('patient.Patient', on_delete=models.CASCADE)
analyzes_group = models.ForeignKey(AnalysisGroup, on_delete=models.CASCADE)
class PatientAnalysis(models.Model):
sheet = models.ForeignKey(PatientAnalysisResultSheet, on_delete=models.CASCADE)
analysis = models.ForeignKey(AnalysisType, on_delete=models.CASCADE)
value = models.FloatField()
patient/models.py:
class Patient(models.Model):
hist_number = models.IntegerField(unique=True)
last_name = models.CharField(max_length=32)
first_name = models.CharField(max_length=32)
def get_absolute_url(self):
return reverse('patient:patient-detail', kwargs={'pk': self.pk})
Now how can I make a form to have an opportunity go on patients page and then add an group of analyses (blood analysis) at once?
Models.py
class Entity(models.Model):
entity = models.CharField(max_length=40)
class Period(models.Model):
period = models.CharField(max_length=10)
class Product(models.Model):
entity = models.ForeignKey(Entity, on_delete=models.CASCADE, default=None, blank=True, null=True)
period = models.ForeignKey(Period, on_delete=models.CASCADE, default=None, blank=True, null=True)
sku = models.CharField(max_length=12)
class Sale(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, default=None, blank=True, null=True)
price = models.DecimalField(max_digits=11, decimal_places=2)
Views.py
if request.method == 'POST':
if form.is_valid():
entityquery = form.cleaned_data['entity']
periodquery = form.cleaned_data['period']
entities = Entity.objects.get(entity=entityquery)
periods = Period.objects.get(period=periodquery)
products = Product.objects.filter(entity=entityquery, period=periodquery).values('id', 'period', 'entity', 'sku')
for sales in products.iterator():
sales = Sale.objects.filter(product__sku=product.sku, product__entity=entityquery, product__period=periodquery).aggregate(Sum('price'))
return sales
args = {'form': form, 'products': products, 'periods': periods, 'entities': entities, 'sales': sales}
return render(request, "products_list.html", args)
Expected Result
So far I am able to list all the SKU items that were sold based on the criteria (Period and Entity). Lets assume SKU 12 has two sales $10 and $30 and SKU 23 has three sales $5, $5 and $6
and I need to show the total sales for each of those products.
Input
Entity: Company XZY
Period: November
Output
SKU Total Sales
12 40.00
23 16.00
It is possible to do group by and SUM using the the django ORM.
How to query as GROUP BY in django?
from django.db.models import Sum
sales = Sale.objects.filter(product__sku=product.sku, product__entity=entityquery, product__period=periodquery).values(`product`).annotate(total = Sum('price'))
Also, in most cases, is very inefficient to loop over a query.
If at all possible, try to use the built-in ORM methods to avoid this.
This is known as a N+1 query problem.
I've been playing around with django for a month now and i'm stuck with JOINING Two tables with Aggregate with it. Here's my models.py
class Student(models.Model):
student_number_format = RegexValidator(regex=r"^20{1,2}[1-2][0-9]-[0-9]{6}", message="Please enter a valid student number (example:2019-123456)")
student_number = models.CharField(validators=[student_number_format], max_length=11, blank=True, unique=True, help_text="Student number must be this format 20YY-99999")
student_course = models.ForeignKey(Course, on_delete=models.CASCADE)
first_name = models.CharField(max_length=255)
middle_initial = models.CharField(max_length=2)
last_name = models.CharField(max_length=255)
profile_picture = models.ImageField(upload_to=user_directory_path)
date_registered = models.DateTimeField(default=timezone.now)
class DataSets(models.Model):
student_info = models.ForeignKey(Student, on_delete=models.CASCADE)
dataset_image = models.ImageField(upload_to=dataset_directory_path)
date_upload = models.DateTimeField(default=timezone.now)
In here i have two models the DataSets class have a Foreign Key to Student. And i want to show only is Students that have 5 or more data inside DataSets. Here's the SQL representation:
SELECT Count(student_info) as Count, A.first_name as Name
FROM Student A
JOIN DataSets B ON A.id = B.student_info_id
WHERE Count >= 5
You can do this with select_relatedlink . I hope following query will work.
DataSets.objects.select_related('student_info').annotate(
entries=models.count()).filter(entries__gte=5)
I try to calculate the average amount for each month for the 13 last month.
So I have a card with the date which has many amounts which are linked to a category.
For example my card 1 has an amount for category A, an amount for category B an amount for category C .... Amount, Card and Category have their own class in the model.
My objective is to calculate for one category, the average amount for each 13 last month.
Here is my model:
class Card(models.Model):
date = models.DateField(auto_now_add=False, null=False)
day = models.IntegerField(null=False)
comment = models.TextField(null=False)
worked = models.BooleanField(default=True)
def __str__(self):
return "<id={}, date={}, day={}, comment={}, worked={}>".format(
self.id,
self.date,
self.day,
self.comment,
self.worked
)
class Category(models.Model):
name = models.CharField(max_length=100)
icon = models.CharField(max_length=50)
order = models.IntegerField(null=False, unique=True)
image = models.CharField(max_length=255)
def __str__(self):
return "<id={}, name={}, icon={}>".format(self.id, self.name, self.icon)
class Amount(models.Model):
amount = models.DecimalField(max_digits=10, decimal_places=2)
card = models.ForeignKey(Card, on_delete=models.CASCADE, related_name='amounts')
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='amounts')
def __str__(self):
return "<id={}, amount={}>".format(self.id, self.amount)
And I have really no idea of how to do this.
Thanks for your help
The solution below uses Django's aggregation and Transform to give you for one category called category the average of the amounts in each month in range(13). If you need it to just be the previous 13 months I would suggest using datetime.timedelta and include a filter on card__date__year. You could also combine the filters below into one line but it gets a little long...
from django.db.models import Avg
amounts_in_category = Amount.objects.filter(category = category)
for month in range(13):
amounts_in_month = amounts_in_category.filter(card__date__month = month)
average_amount_for_month = amounts_in_month.aggregate(Avg('amount'))
I have a field in a model that I would like to be a choice or blank. There may be as many blank items as possible but need to be unique for all others ie there may not be two specials on the same day.
Here is my views.py
class Item(models.Model):
CATEGORY_CHOICES = (('Sandwich', 'Sandwich'), ('Salad', 'Salad'), ('Slider', 'Slider'), ('Side', 'Side'), ('Drink', 'Drink'))
DAYS = (('Monday','Monday'), ('Tuesday','Tuesday'), ('Wednesday','Wednesday'), ('Thursday','Thursday'), ('Friday','Friday'), ('Saturday','Saturday'), ('Sunday','Sunday'))
name = models.CharField(max_length=50)
description = models.TextField()
category = models.CharField(max_length=50)
price = models.DecimalField(max_digits=6, decimal_places=2)
category = models.CharField(max_length=30, choices=CATEGORY_CHOICES)
order = models.PositiveSmallIntegerField(default=0, blank=True, null=True)
special = models.BooleanField(default=False)
day = models.CharField(max_length=30, choices=DAYS, unique=True, blank=True)
publish = models.DateField(auto_now=False, auto_now_add=False),
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.name
I am also trying to order the daily specials by day of the week ie (Monday, Tuesday, etc) and I thought the following view was working but it seems to be ordering the Items by id
def specials(request):
specials_list = Item.objects.filter(special = True).order_by('day')
context = {
'specials_list': specials_list,
}
return render(request, 'menu/specials.html', context)
Thanks in advance for the help!
From Django Docs
Unless blank=False is set on the field along with a default then a label containing "---------" will be rendered with the select box. To override this behavior, add a tuple to choices containing None; e.g. (None, 'Your String For Display'). Alternatively, you can use an empty string instead of None where this makes sense - such as on a CharField.
So, for you to allow for a blank choice in any of your tuples, just add the bolded text from the above quote
eg:
CATEGORY_CHOICES = (('Sandwich', 'Sandwich'), ('Salad', 'Salad'), ('Slider', 'Slider'), ('Side', 'Side'), ('Drink', 'Drink'), ('None', 'N/A'))
As for being unique, you already have the days of the week set as unique.