How to get data from two table through one query Django - django

** I just need one more table join in my query **
I want to get sales of logged-in users with order detail and shipping address.
I am getting sales of current user through this query but i also want get shipping address.
orderitems = OrderItem.objects.filter(
product__user=request.user, order__complete=1).order_by('-date_orderd')
Now i want to get also address, city and state from the Shippingaddress model.
I attached the models below.
this is my current result.
My models:
Order Model:
class Order(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
date_orderd = models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False, null=True, blank=False)
transaction_id = models.CharField(max_length=200, null=True)
# product = models.ManyToManyField(OrderItem)
def __str__(self):
return str(self.id)
Order items Model:
class OrderItem(models.Model):
product = models.ForeignKey(
Product, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(
Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_orderd = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
price = models.FloatField(blank=True, null=True)
def __str__(self):
return str(self.product)
Shipping Address Model:
class ShippingAddress(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(
Order, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=150)
address = models.CharField(max_length=150)
city = models.CharField(max_length=150)
state = models.CharField(max_length=150)
zipcode = models.CharField(max_length=150)
date_orderd = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address

What you are looking for is "Select from multiple tables in one query with Django". You can take a look at the answers here.

Why not add another query like the one below
shp_address = ShippingAddress.objects.filter(product__user=request.user)
and if needed send to the client side as part of context, see below
context = {
'orderitems': orderitems,
'shp_address': shp_address
}

Related

Joining more than 2 tables for reports in django and extract all the fields from the joined table

I am joining the ClientDetails, AssignmentTable and CallDetails table to get a view as to which telecaller a particular client has been assigned to and get the latest call details as well. However I am unable to accomplish that using django ORM.
ISSUE:
I am trying to access the fields inside the assignment table and call table but I am getting only the ids and not the other fields.
Question:
How do I extract all the columns from the assignment and call details table which has the client id as 1?
This is the SQL Query that I am trying to come up with:
SELECT t1.uid, t1.phone_number, t1.client_name, t1.base, t1.location, t2.assigner, t2.bpo_agent, t2.cro_agent, t3.bpo_status_id, t3.cro_status_id, t3.agent_id_id
FROM public.bpo_app_clientdetails t1
LEFT JOIN public.bpo_app_assignmentdetails t2 ON t1.uid = t2.client_id_id
LEFT JOIN public.bpo_app_calldetails t3 ON t1.uid = t3.client_id_id;
Below is the model file:
class ClientDetails(models.Model):
uid = models.AutoField(primary_key=True)
phone_number = PhoneNumberField(unique=True)
client_name = models.CharField(max_length=50, blank=True, null=True)
base = models.CharField(max_length=50, blank=True, null=True)
location = models.CharField(max_length=50, blank=True, null=True)
class Meta:
verbose_name_plural = "Client Contact Detail Table"
def __str__(self):
return f"{self.phone_number}, {self.client_name}"
class AssignmentDetails(models.Model):
uid = models.AutoField(primary_key=True)
client_id = models.ForeignKey(
ClientDetails,
on_delete=models.PROTECT,
related_name='assignment_details'
)
date_and_time = models.DateTimeField(auto_now_add=True, blank=True)
assigner = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='AssignerAgent',
db_column='assigner',
)
bpo_agent = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='bpoAgent',
db_column='bpo_agent',
)
cro_agent = models.ForeignKey(
User,on_delete=models.PROTECT,
related_name='croAgent',
db_column='cro_agent',
)
class Meta:
verbose_name_plural = "Client Assignment Detail Table"
def __str__(self):
return f"{self.uid}"
class CallDetails(models.Model):
uid = models.AutoField(primary_key=True)
date_and_time = models.DateTimeField(auto_now_add=True, blank=True)
client_id = models.ForeignKey(
ClientDetails,
on_delete=models.PROTECT,
related_name='call_details'
)
agent_id = models.ForeignKey(EmployeeDetails_lk,on_delete=models.PROTECT)
bpo_status = models.ForeignKey(BpoStatus_lk,on_delete=models.PROTECT, blank=True, null=True)
cro_status = models.ForeignKey(CroStatus_lk,on_delete=models.PROTECT, blank=True, null=True)
required_loan_amt = models.CharField(max_length=50, blank=True, null=True)
remarks = models.CharField(max_length=500, blank=True, null=True)
loan_program = models.ForeignKey(LoanProgram_lk, on_delete=models.PROTECT, blank=True, null=True)
disbursement_bank = models.ForeignKey(Banks_lk, on_delete=models.PROTECT, limit_choices_to={'loan_disbursement_status': True}, blank=True, null=True)
class Meta:
verbose_name_plural = "Client Call Detail Table"
def __str__(self):
return f"{self.uid}"
>>> qry=ClientDetails.objects.values('assignment_details','call_details').filter(uid=1)
>>> qry
<QuerySet [{'assignment_details': 1, 'call_details': None}]>
>>> print(a.query)
SELECT "bpo_app_assignmentdetails"."uid", "bpo_app_calldetails"."uid" FROM "bpo_app_clientdetails" LEFT OUTER JOIN "bpo_app_assignmentdetails" ON ("bpo_app_clientdetails"."uid" = "bpo_app_assignmentdetails"."client_id_id") LEFT OUTER JOIN "bpo_app_calldetails" ON ("bpo_app_clientdetails"."uid" = "bpo_app_calldetails"."client_id_id") WHERE "bpo_app_clientdetails"."uid" = 1
You can use prefetch_related() to achieve this. I just use some sample models here for better understanding.
class Company(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
class Project(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
class Employee(models.Model):
name = models.CharField(null=True, blank=True, max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
In your views.py function write the below lines to get the desired results
companies = Company.objects.filter(id=1).prefetch_related('project_set', 'employee_set')
for company in companies:
print(company.project_set.values()) # This will print this company projects
print(company.employee_set.values()) # This will print this company employees
Note: If you use related_name in your ForeignKey relationship, make sure that you access with that name instead of model_set inside prefetch_related()

how to make relationship in django model

models.py
So,here i want to make Invoicemgmt model in which i can have multiple entries for Invoice table having
customer,project and Invoice_amount.
Basically,requirement is that whenever i see 'view_Invoice' of some id,first i will see all data of that
specific id on that page and then i want to have small table below for invoice_mgmt,where i can add amount received for that specific id invoice.
*so,i want to know what fields should i add in invoice_mgmt model for relationship "
class Invoice(models.Model):
company_choice = (
('VT_India', 'VT_India'),
('VT_USA', 'VT_USA'),
)
company = models.CharField(
max_length=30, blank=True, null=True, choices=company_choice)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
project = models.ForeignKey(Allproject, on_delete=models.CASCADE)
invoice_title = models.CharField(max_length=15)
invoice_id = models.IntegerField(primary_key=True)
invoice_amount = models.IntegerField()
invoice_date = models.DateField(
blank=True, null=True)
invoice_duedate = models.DateField(
blank=True, null=True)
invoice_description = models.TextField()
def __str__(self):
return self.invoice_title
class Paymentmethod(models.Model):
paymentmethod_id = models.IntegerField(primary_key=True)
paymentmethod_name = models.CharField(max_length=15)
def __str__(self):
return self.paymentmethod_name
class Invoicemgmt(models.Model):
invoicemanagement_id = models.IntegerField(primary_key=True)
invoice_received = models.IntegerField()
date = models.DateField(
blank=True, null=True)
payment_method = models.ForeignKey(Paymentmethod, on_delete=models.CASCADE)
"So, basically i want to have multiple entries in invoice mgmt table for one specific invoice table id(one specific data)"

How to clone a model instance without cloning database relationship?

I'm building a cart model with the following code.
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=200)
price = models.DecimalField(max_digits=8, decimal_places=2)
def __str__(self):
return self.name
class Order(models.Model):
date = models.DateTimeField(auto_now_add=True)
transcation_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.date)
class OrderItem(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.CASCADE, blank=True, null=True)
quantity = models.IntegerField(default=0, blank=True, null=True)
The many-to-one relationship between Item and Order allows one Order to contain many Item and that looks fine.
A model instance can be simply cloned as already answer in this question.
My problem is, if the price of an Item is changed. The price of contained items in Order is change too. But I don't want it to be changed. In the situation that customer already make a purchase, the price cannot be change. Is there anyway to clone the Order instance that completely not related to the other model?
Save the price manually
class OrderItem(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, blank=True, null=True)
order = models.ForeignKey(Order, on_delete=models.CASCADE, blank=True, null=True)
quantity = models.IntegerField(default=0, blank=True, null=True)
price = price = models.DecimalField(max_digits=8, decimal_places=2, null=True, default=None)
def save():
if self.pk == None:
self.price = self.item.price
super(OrderItem, self).save()

how to use two instance id of foreign key

I have four models of the shop, customer, product, an order.
I am showing the relation of models
shop
user = models.OneToOneField(User, null=True, related_name='shop', blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=70, null=True, default='shop', )
address = models.CharField(max_length=70, null=True)
Shop_category = models.CharField(max_length=200, null=True, )
customer
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=100, null=True, default='customer')
Phone = models.PositiveIntegerField(blank=True, null=True)
product
shop = models.ForeignKey(Shop, models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=100, blank=True)
Brand = models.CharField(max_length=200, blank=True)
description = models.TextField(null=True, blank=True)
order
shop = models.ForeignKey(Shop, models.CASCADE, null=True)
customer = models.ForeignKey(Customer, models.CASCADE, null=True)
product = models.ForeignKey(Product, models.CASCADE, null=True)
quantity = models.CharField(max_length=30)
date_created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=200, choices=STATUS, default='Pending')
note = models.CharField(max_length=1000, null=True)
when customers login then the shop will print on the screen and a button on shop to show the products by the shop in the form card. On the product card, there is an order button that adds the product in order after submitting the selected product will print with the remaining filled of order that shown in the image
how I create order form show that I get the id of shop and product
If you are getting the id of shop and product then you can create order in this way
def your_view_function(request,shop_id,product_id):
customer = request.user.customer
shop = Shop.objects.get(id=shop_id)
product = Product.objects.get(id=product_id)
# assuming you are getting value of quantity and note
quantity = request.POST.get('quantity')
note = request.POST.get('note')
# or you are getting quantity and note from form
order = Order.objects.create(customer=customer,shop=shop,product=product,quantity=quantity,note=note)

Update an instance of a model in django such that the older instance and its relationship with other instances remain unaffected

I have been working on a e-commerce project. I have three models Item, OrderItem, Order. They are linked with Foreignkey(s) (Item -> OrderItem -> Order). Item is the actual product and an Order contain(s) Item(s).
Item basically represents a product. In Item there is an attribute 'price' which needs to updated as need suggest. Like during a sale or something else.
What happens is when I update the price of an Item, the price of that item also gets updated in the instances of the Order(s) that are already completed.
Basically I would want to separate these models in a way such that any changes in the Item model doesn't effect the Orders that are completed.
class Item(models.Model):
title = models.CharField(max_length=100)
sku = models.CharField(max_length=8, validators=[
MinLengthValidator(8)], unique=True)
upc = models.CharField(max_length=12, validators=[
MinLengthValidator(12)], unique=True, blank=True, null=True)
date_updated = models.DateTimeField(
auto_now=True, blank=True, null=True)
price = models.FloatField()
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField(upload_to=upload_location, blank=True, null=True)
stock_quantity = models.IntegerField(default=0)
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
item_variations = models.ManyToManyField(ItemVariation)
quantity = models.IntegerField(default=1)
purchase = models.FloatField(blank=True, null=True)
def get_total_item_price(self):
return self.quantity * self.item.price
class Order(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
ref_code = models.CharField(
max_length=20, blank=True, null=True, unique=True)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
# Check this
ordered_date = models.DateTimeField()
# When the payment is made it becomes True
ordered = models.BooleanField(default=False)
shipping_address = models.ForeignKey(
'Address', related_name='shipping_address', on_delete=models.SET_NULL, blank=True, null=True)
billing_address = models.ForeignKey(
'Address', related_name='billing_address', on_delete=models.SET_NULL, blank=True, null=True)
payment = models.ForeignKey(
'Payment', on_delete=models.SET_NULL, blank=True, null=True)
coupon = models.ForeignKey(
'Coupon', on_delete=models.SET_NULL, blank=True, null=True)
being_delivered = models.BooleanField(default=False)
received = models.BooleanField(default=False)
refund_requested = models.BooleanField(default=False)
refund_granted = models.BooleanField(default=False)
refund_refused = models.BooleanField(default=False)
Any help will be appreciated, thank you.
You could have ItemPrice as a separate model with a One-to-Many relationship. Which prices for the item are stored with associated date changed.
models.py
class ItemPrice(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
price = models.FloatField()
date_changed = models.DateTimeField(auto_now=True, blank=True, null=True)
Then align your order date with the items price at that current time.