Display data from multiple tables in one Template - django

I'm trying to create a dashboard for orders placed by a customer. I've got multiple tables, but the two I'm dealing with is "Order" and "Order_Detail". From the "Order" table, I need to display Customer, Status, and Required_date, from the "Order_Detail" table, I need Product. I'm able to access the data but I can figure out how to display all the records at the same time on one page.
models.py
class Order(models.Model):
STATUS = (
('New', 'New'),
('Ready For Fullfillment', 'Ready For Fullfillment'),
('Fullfilled Ready For Delivery', 'Fullfilled Ready For Delivery'),
('Out For Delivery', 'Out For Delivery'),
('Delivered', 'Delivered'),
)
order_date = models.DateTimeField(auto_now_add=True, null=True)
required_date = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
note = models.CharField(max_length=1000, null=True, blank=True)
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.customer.name
class Order_Detail(models.Model):
orderNumber = models.ForeignKey(Order, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
pounds = models.IntegerField(null=True)
ounces = models.IntegerField(null=True)
container = models.ForeignKey(Container, null=True, on_delete=models.SET_NULL)
lot_code = models.CharField(max_length=200, null=True, blank=True)
note = models.CharField(max_length=1000, null=True, blank=True)
In my views.py, I'm playing with the following code:
print('TEST2')
o = Order.objects.all()
o_notdelivered = Order.objects.exclude(status='Delivered')
for e in o_notdelivered:
print('Order ID:', e.id)
order_detail_data = serializers.serialize("python", Order_Detail.objects.all().filter(orderNumber=e.id))
print('order_detail_data:', order_detail_data)
With that code, I'm able to get the ORDER data and related ORDER_DETAIL data, but I can't figure out how to put the fields I need together and send it to my template. Please note that their will be multiple orders and order_details that will need to go to the template.
Basically, in the end, I want, on my dashboard a table that looks like this:
|Customer|Product|Required Date|Status|
|-|-|-|-|
|C1|Product1|date here|New|
|C2|Product3|date here|New|

In your template (.html file) you have to access this variables, for example, if you want to show the status of all packages, then, in the html file you should write something like:
{% for object in o %} <!-- Works like in python-->
<h1>{{object.status}}</h1>
<!-- Do this for all other attributes-->
{% endfor %} <!-- Must close 'for loop'-->

use this query in your views Order_Detail.objects.all() and pass the context.
views.py
order_details = Order_Detail.objects.all()
context = {'order_details':order_details }
....your others code
then in your html:
{{order_details.product}} #accessing data from your Order_Detail model
{{order_details.orderNumber.status}} #accessing data from your Order model via foreignkey

Related

When "select_related" is needed?

In my project , Each candidate can takepart in some assessments,each assessment has some tests, each test has some questions in it and candidates should answer the questions
at last scores of the questions are saved in question_score and test_score table
I need to get some values of field and use them
I write a method for question_result table, to get them
but i dont know if it is needed to use select_related or not
if it is needed how can i use it ?
Assessment:
class Assessment(BaseModel):
company = models.ForeignKey(
'company.Company',
on_delete=models.CASCADE,
related_name='assessments',
)
title = models.CharField(max_length=255)
job_role = models.ForeignKey(
JobRole,
on_delete=models.PROTECT,
related_name='assessments',
blank=True,
null=True,
)
tests = models.ManyToManyField(
'exam.Test',
related_name='assessments',
blank=True,
through='TestOfAssessment',
)
candidates = models.ManyToManyField(
'user.User',
related_name='taken_assessments',
blank=True,
through='candidate.Candidate'
)
def __str__(self):
return self.title
Test:
class Test(BaseModel):
class DifficultyLevel(models.IntegerChoices):
EASY = 1
MEDIUM = 2
HARD = 3
company = models.ForeignKey(
'company.Company',
on_delete=models.PROTECT,
related_name='tests',
null=True,
blank=True,
)
questions = models.ManyToManyField(
'question.Question',
related_name='tests',
blank=True,
help_text='Standard tests could have multiple questions.',
)
level = models.IntegerField(default=1, choices=DifficultyLevel.choices)
title = models.CharField(max_length=255)
summary = models.TextField()
def __str__(self):
return self.title
Question :
class Question(BaseModel):
company = models.ForeignKey(
'company.Company',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='company_questions',
)
question_text = models.TextField()
def __str__(self):
return truncatewords(self.question_text, 7)
TestResult:
class TestResult(BaseModel):
candidate = models.ForeignKey(
'Candidate',
on_delete=models.CASCADE,
related_name='test_results',
)
test = models.ForeignKey(
'exam.Test',
on_delete=models.CASCADE,
)
test_score = models.DecimalField(default=0.00, max_digits=5, decimal_places=2)
def __str__(self):
return f'{self.candidate.user.email} - {self.test.title}'
Candidate :
class Candidate(BaseModel):
assessment = models.ForeignKey(
'assessment.Assessment',
on_delete=models.CASCADE,
)
user = models.ForeignKey(
'user.User',
on_delete=models.CASCADE,
)
is_rejected = models.BooleanField(default=False)
def __str__(self):
return f'{self.user.email} - {self.assessment.title}'
Company :
class Company(models.Model):
manager = models.ForeignKey('user.User', on_delete=models.CASCADE, related_name='user_companies')
name = models.CharField(max_length=255)
city = models.ForeignKey('company.City', null=True, on_delete=models.SET_NULL)
address = models.CharField(max_length=255, blank=True, null=True)
def __str__(self):
return self.name
QuestionResult :
class QuestionResult(BaseModel):
test = models.ForeignKey(
'TestResult',
on_delete=models.CASCADE,
related_name='question_results',
)
question = models.ForeignKey(
'question.Question',
on_delete=models.CASCADE,
related_name='results',
)
result = models.TextField(
null=True,
blank=True,
)
answer_score = models.DecimalField(default=0.00, max_digits=5, decimal_places=2)
def __str__(self):
return f'{self.test.candidate.user.email} - {self.question}'
def text_variables(self):
email = self.test.candidate.user.email
company_name = self.test.test.company.name
assessment_name = self.test.candidate.assessment.title
candidate_first_name = self.test.candidate.user.first_name
job_name = self.test.candidate.assessment.job_role
user_fullname = User.full_name
data = dict(
job_name=job_name,
company_name=company_name,
email=email,
assessment_name=assessment_name,
candidate_first_name=candidate_first_name,
job_name=job_name,
user_fullname = user_fullname
)
return data
I wrote the def text_variables(self): method to fill the data dictionary and use it somewhere else
it work properly but i dont know if it needed to use selected_related or not
something like this (it does not work)
def text_variables(self):
question_result_object = QuestionResult.objects.filter(id=self.id).select_related(
"test__candidate","test__test__company","test__candidate__assessment")
email = question_result_object.test.candidate.user.email
company_name = question_result_object.test.test.company.name
assessment_name = question_result_object.test.candidate.assessment.title
candidate_first_name = question_result_object.test.candidate.user.first_name
job_name = question_result_object.test.candidate.assessment.job_role
data = dict(
job_name=job_name,
company_name=company_name,
email=email,
assessment_name=assessment_name,
candidate_first_name=candidate_first_name,
job_name=job_name,
user_fullname = user_fullname
)
return data
the error is :
File "E:\work\puzzlelity\talent-backend\candidate\models.py", line 385, in report_to_candidate_email_text_variables
email = question_result_object.test.candidate.user.email
AttributeError: 'QuerySet' object has no attribute 'test'
[03/Jan/2023 17:59:00] "POST /api/v1/candidatures/183f8432-ea81-4099-b211-3b0e6475ffab/submit-answer/ HTTP/1.1" 500 123319
I dont know how should i use the select_related
It's never required. It optimizes querysets, especially in ListViews.
Consider your Assessment model. It has ForeignKey fields company and job_role. If you simply fetch
assessment = Assessment.objects.get( id=something)
and then refer to assessment.company, that causes a second DB query to fetch the company object. And then a third if you refer to assessment.job_role.
You can reduce these three queries to one by using
assessment = Assessment.objects.select_related(
'company', 'job_role') .get( id=something)
which does a more complex query to retrieve all the data.
Where it matters is in a list view where you iterate over a large number of assessment objects in Python or in a template. For example, if object_list is assessment.objects.all() and there are 300 of them, then
{% for assessment in object_list %}
... stuff ...
{{assessment.company.name }}
...
{% endfor %}
Will hit the DB 300 times, once for each company! If you use select_related, all 300 companies linked to the 300 assessments will be retrieved in a single DB query. which will be very noticeably faster.
I'd strongly recommend installing Django Debug Toolbar in your development project. Then click on the SQL option on any view, and you can see what SQL was required, and in particular how many SQL queries were performed and whether there were batches of repetetive queries which mean there's a trivial optimisation to be made.

How to copy a object data to another object in Django?

I am trying to create an E-Commerce Website and I am at the Final Step i.e. Placing the Order. So, I am trying to add all the Cart Items into my Shipment model. But I am getting this error.
'QuerySet' object has no attribute 'product'
Here are my models
class Product(models.Model):
productId = models.AutoField(primary_key=True)
productName = models.CharField(max_length=200)
productDescription = models.CharField(max_length=500)
productRealPrice = models.IntegerField()
productDiscountedPrice = models.IntegerField()
productImage = models.ImageField()
productInformation = RichTextField()
productTotalQty = models.IntegerField()
alias = models.CharField(max_length=200)
url = models.CharField(max_length=200, blank=True, null=True)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, null=True, blank=True)
email = models.EmailField(max_length=100)
profileImage = models.ImageField(blank=True, null=True, default='profile.png')
phoneNumber = models.CharField(max_length=10, blank=True, null=True)
address = models.CharField(max_length=500, blank=True, null=True)
class Order(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
dateOrdered = models.DateTimeField(auto_now_add=True)
orderCompleted = models.BooleanField(default=False)
transactionId = models.AutoField(primary_key=True)
class Cart(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity = models.IntegerField(default=0, blank=True, null=True)
dateAdded = models.DateTimeField(auto_now_add=True)
class Shipment(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, blank=True, null=True)
orderId = models.CharField(max_length=100)
products = models.ManyToManyField(Product)
orderDate = models.CharField(max_length=100)
address = models.CharField(max_length=200)
phoneNumber = models.CharField(max_length=13)
I just removed additional functions i.e. __str__ and others.
Here is the views.py
def orderSuccessful(request):
number = Customer.objects.filter(user=request.user).values('phoneNumber')
fullAddress = Customer.objects.filter(user=request.user).values('address')
timeIn = time.time() * 1000 # convert current time in milliSecond
if request.method == 'POST':
order = Shipment.objects.create(customer=request.user.customer, orderId=timeIn,
orderDate=datetime.datetime.now(), address=fullAddress,
phoneNumber=number)
user = Customer.objects.get(user=request.user)
preOrder = Order.objects.filter(customer=user)
orders = Order.objects.get(customer=request.user.customer, orderCompleted=False)
items = orders.cart_set.all() # Here is all the items of cart
for product in items:
product = Product.objects.filter(productId=items.product.productId) # error is on this line
order.products.add(product)
Cart.objects.filter(order=preOrder).delete()
preOrder.delete()
order.save()
else:
return HttpResponse("Problem in Placing the Order")
context = {
'shipment': Shipment.objects.get(customer=request.user.customer)
}
return render(request, "Amazon/order_success.html", context)
How to resolve this error and all the cart items to field products in Shipment model?
Your model is not really consistent at all. Your Cart object is an m:n (or m2m - ManyToMany) relationship between Product and Order. Usually, you would have a 1:n between Cart and Product (a cart contains one or more products). One Cart might be one Order (unless you would allow more than one carts per order). And a shipment is usually a 1:1 for an order. I do not see any of this relationships in your model.
Draw your model down and illustrate the relations between them first - asking yourself, if it should be a 1:1, 1:n or m:n? The latter can be realized with a "through" model which is necessary if you need attributes like quantities.
In this excample, we have one or more customers placing an order filling a cart with several products in different quantities. The order will also need a shipment fee.
By the way: bear in mind that "filter()" returns a list. If you are filtering on user, which is a one to one to a unique User instance, you would better use "get()" as it returns a single instance.
Putting in into a try - except or using get_object_or_404() makes it more stable.
product = Product.objects.filter(productId=items.product.productId)
should be something like:
product = product.product
not to say, it becomes obsolete.
It looks like you make a cart for a product by multiple instances of Cart, the problem is you try to access the wrong variable, also you don't need to filter again when you already have the instance, make the following changes:
carts = orders.cart_set.all() # Renamed items to carts for clarity
for cart in carts:
product = cart.product
order.products.add(product) # The name order is very misleading makes one think it is an instance of Order, actually it is an instance of Shipment
As mentioned above in my comment your variable names are somewhat misleading, please give names that make sense to any variable.

Django Joining Tables

I am trying to get the information from one table filtered by information from another table (I believe this is called joining tables).
I have these two models:
class Listing(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=500)
price = models.DecimalField(max_digits=11, decimal_places=2, validators=[MinValueValidator(Decimal('0.01'))])
category = models.ForeignKey(Category, on_delete=models.CASCADE, default="")
imageURL = models.URLField(blank=True, max_length=500)
creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name="creator", default="")
isOpen = models.BooleanField(default=True)
def __str__(self):
return f"{self.id} | {self.creator} | {self.title} | {self.price}"
class Watchlist(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="listingWatched", default="")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="userWatching", default="")
What I need to do is to get all the listings from a specific user Watchlist, the idea is to generate a page with all of the information of each of the listings that are in the user's watchlist. What should I do?
Thanks in advance!
Since is a foreign key, in Django you can access the information by calling the attribute
For example:
my_user = Watchlist.objects.get(pk=1)
print(my_user.listing.title)
You can also access to that attrbute in a query in case you need to filter upwards some value
values = Watchlist.objects.all().filter(listing__title='MyTitle')
my_titles = [x.title for x in values]
print(my_titles)
Or in your case, if you want to list all the title for a specific user
values = Watchlist.objects.all().filter(user='foo_user')
my_titles = [x.listing.title for x in values]
print(my_titles)
More documentation here

Django trying to add up values in the django template

Hi Guys I am trying to figure this out but not having any luck.
So I am showing my events in the homepage which shows how many seats are available, once the user has made a booking I would like to minus that from the amount showing on the homepage.
But I am already stuck at adding all the values up for that event in the booking model to minus from that amount.
So this is what I have
model for events
class Events(models.Model):
ACTIVE = (('d', "Deactivated"), ('e', "Expired"), ('a', "Active"), ('b', "Drafts"),)
ALCOHOL = (('0','No bring own alcohol'),('1','There will be complimentary wine pairing'))
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=50, blank=True, default='')
date = models.DateField()
time = models.TimeField()
price = models.CharField(max_length=240, blank=True, default='')
seats = models.IntegerField()
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
model for bookings
class Bookings(models.Model):
OPTIONS_STATUS = (('y', "Yes"), ('n', "No"), ('p', "Pending"),)
user = models.ForeignKey(User, on_delete=models.CASCADE)
event = models.ForeignKey(Events, on_delete=models.CASCADE)
eventdate = models.DateField()
event_amount = models.CharField(max_length=50, blank=True, default='')
guests = models.IntegerField()
bookingstatus = models.CharField(max_length=50, default='p', blank=True, choices=OPTIONS_STATUS)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
my homepage how I get my data into a loop form the view
today = datetime.now().strftime('%Y-%m-%d')
events_list_data = Events.objects.filter(active='a').filter(Q(date__gte=today)|Q(date=today)).order_by('date')
How I am trying to show this in my template
{% for event_list in events_list_data %}
SHOW WHAT EVER DATA I AM SHOWING NOT NEEDED FOR HELP ON
{% for bookingguests in
event_list.bookings_set.all %}
{{ bookingguests.guests }}
{% endfor %}
Seats Left
{% endif %}
Generally, purpose of templates is not to implement logic. All the logic should go into your views. I would recommend you to do that in your views and either store it in a dict or a list and send it to front-end.
Once the user made a booking, if you want to modify the value on the HTML without reloading, you may need to use jQuery/javascript. Otherwise, if you are fine with reloading the page by rendering it again with calculations from the backend.
By using jQuery:
$("#balance-id").html(logic to get the balance)
By Calculating in views:
from django.db.models import Sum
user_balance = user.balance - events_data.aggregate(Sum('price'))
return render('path/to/template', {'events_list': events_list_object, 'user_balance':user_balance})
In the template:
{{user_balance}} seats left
Let me know in case of any questions.
Note: If you want to write some logic into your templates, use template tags. It can help you with whatever it can with its limited functionality.

Django Master to Child table with customization

I have master to child tables, need a solution to render it with below condition.
Master Table Fields:-
Person product categ price image field1 field2
Child Table (User customised):-
User Product categ customprice customfield1 customfield2
Query:-
totalrecords = Master.objects.filter(Person=person1).filter(categ=catogory1)
enabledrecords = Child.objects.filter(user=user).filter(categ=categ1)
product in child is foreign key from Master.
In template I will extract the master fields(in for loop) but if price and customfields exists in child then I need to take child object using product relation, otherwise populate these from master table.
Here the confusion comes,
{% for obj in totalrecords %}
if obj.id in enabledrecords (using product forign key) then
Get en_obj from enabledrecords__product
{{obj.id}} {{en_obj.id}} {%if en_obj.customprice%} {{en_obj.customprice}}
{%else%}{%obj.price%}{%endif%} -->do same for other customfields
if obj.id not in enabledrecords
{{ obj.id }} <p> Product not customized click here to customise </p>
Please advice.
EDIT:
Products(Master Table):-
vendor = models.ForeignKey(Shop,verbose_name='Shop Name')
name = models.CharField('Product Name', max_length=100 )
pfimage = models.ImageField('Image', upload_to='pd/%Y',)
pdctg = models.ForeignKey(PdCtg, null=True, blank=True, verbose_name='Product Category')
mrp =models.DecimalField('MRP (optional)',max_digits=6, decimal_places=2, null=True, blank=True)
ourprice =models.DecimalField('Our Price (optional)',max_digits=6, decimal_places=2, null=True, blank=True)
offer =models.CharField('Offers (optional)',max_length=10, null=True, blank=True)
Child Table:
vendor =models.ForeignKey(Shop,verbose_name='Shop Name')
pdctg = models.ForeignKey(PdCtg,null=True, blank=True,verbose_name='Product Category')
products =models.ForeignKey(Products, verbose_name='Product Name')
pdid =models.CharField('Item ID',max_length=100, null=True, blank=True)
mrp =models.DecimalField('MRP (optional)',max_digits=6, decimal_places=2, null=True, blank=True)
ourprice =models.DecimalField('Our Price (optional)',max_digits=6, decimal_places=2, null=True, blank=True)
offer =models.CharField('Offers (optional)',max_length=10, null=True, blank=True)
Child table may or may not have all rows of master for a given vendor and pdctg