Duplicated django ORM query n+1 - python

I have a models looks like this
class Transaction(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
income_period_choices = (("Weekly", "Weekly"), ("Fortnightly", "Fortnightly"))
chp_reference = models.CharField(max_length=50, unique=True)
rent_effective_date = models.DateField(null=True, blank=True)
class FamilyGroup(models.Model):
name = models.CharField(max_length=10, choices=name_choices)
transaction = models.ForeignKey(
Transaction, on_delete=models.CASCADE, related_name="family_groups"
)
family_type = models.ForeignKey(
FamilySituation, on_delete=models.PROTECT, null=True, blank=True
)
last_rent = models.DecimalField(
help_text="per week", max_digits=7, decimal_places=2, null=True, blank=True
)
#property
def rent_assessment_rate(self):
return RentAssessmentRate.objects.get(active="Yes") # here i think i should add select_related maybe or something, but im not sure
#property
def ftb_rate(self):
return self.rent_assessment_rate.ftb
#property
def cra_rate(self):
return self.rent_assessment_rate.cra
#property
def maintenance_rate(self):
return self.rent_assessment_rate.maintenance
views
def index(request):
transaction = Transaction.objects.all().prefetch_related('family_groups')
return render(request, 'cra/index.html', {"transaction":transaction})
So I'm getting a duplicated queries from RentAssessmentRate table while trying to retrieve the data on the FamilyGroup table.
What would be a good approach to avoid such duplicates? Thanks in advance

Related

Cannot assign "'Sample Category'": "Product.category" must be a "Category" instance

While creating new products I'm getting such kind of error. Can someone help me?
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name_geo = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.ForeignKey(Category, null=False, default=0, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name_geo
class Category(models.Model):
_id = models.AutoField(primary_key=True, editable=False)
name = models.CharField(max_length=200, null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
#api_view(['POST'])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category="Sample Category",
price=0,
brand='Sample Brand',
countInStock=0,
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
Without separating category class in models.py everything works fine. I mean If i didn't use ForeignKey in Products class for category
It just has to be a Category Instance/Object
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category=Category.objects.get_or_create(name="Sample Category"),
price=0,
brand='Sample Brand',
countInStock=0,
)
Notes:
You could just do a .get() or a .filter().first() if you don't want to create
If you use a form, you can get away with just the Category's PK/_id in the POST
this type of thing: f = form(request.POST) f.is_valid() f.save()
At the end that field will hold the PK/_id/Row# of the Category Obj

How to display only the appointments that the current logged in user has made instead of fetching up all the appointments from the database in Django

This the views.py file.
How can i display the appointments made by the current logged in user?
def user(request):
client = Client.objects.all()
appointments = Appointment.objects.all()
context = {'appointments': appointments, 'client': client,
}
return render(request, 'users/user.html', context)
Here is my Models.py. I need to display the appointments by a user when they are logged in to their profile.
class Appointment(models.Model):
CATEGORY = (
('Plumbing', 'Plumbing'),
('Electrical', 'Electrical'),
('Cleaning', 'Cleaning'),
)
STATUS = (
('Pending', 'Pending'),
('Delivered', 'Delivered'),
)
user = models.ForeignKey(Client, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200, null=True)
worker = models.ForeignKey(Worker, null=True, on_delete=models.SET_NULL)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
task_date = models.DateField(_("Task Date"), blank=True, null=True)
task_location = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
budget = models.FloatField(null=True)
task_description = models.CharField(max_length=1000, null=True)
task_image = models.ImageField(
null=True, blank=True, help_text='Optional.')
def __str__(self):
return str(self.user)
instead of using all() in your query use filter()
all() gives you all the entries in the table.
do something like this:
appointments = Appointment.objects.filter(user = request.user)
the left side "user" inside the filter must be a column in the Appointment model/table. you can pass multiple parameters inside the filter.
Yea it worked. but i had to create a one to one relatioship between appointment and User

automatically add a new models to admin page

i have a calculator app, inside it i have a Transaction , Family_group , Family_member models see pic below.
i want everytime i try to make a new Transaction there will be a default 1 Family_group and Family_member added automatically, without me starting one each time. is there any way to do it ?
models.py
class Transaction(models.Model):
income_period_choices = (('Weekly', 'Weekly'), ('Fortnightly',
'Fortnightly'))
chp_reference = models.CharField(max_length=50, unique=True)
rent_effective_date = models.DateField(null=True, blank=True)
income_period = models.CharField(max_length=11,
choices=income_period_choices,
null=True,
blank=True, default='Weekly')
property_market_rent = models.DecimalField(help_text='Weekly',
max_digits=7,
decimal_places=2,
null=True,
blank=True)
class FamilyGroup(models.Model):
name_choices = (('FG_1', 'FG_1'), ('FG_2',
'FG_2'), ('FG_3', 'FG_3'), ('FG_4',
'FG_4'), ('FG_5', 'FG_5'))
name = models.CharField(max_length=10, choices=name_choices)
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
family_type = models.ForeignKey(FamilySituation,
on_delete=models.PROTECT,
null=True,
blank=True)
class FamilyMember(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
family_group = models.ForeignKey(FamilyGroup,
on_delete=models.CASCADE,
null=True,
blank=True)
name = models.CharField(max_length=100, null=True, blank=True)
date_of_birth = models.DateField(null=True, blank=True)
relationship = models.ForeignKey(Relationship, on_delete=models.PROTECT)
Without seeing your code, it's hard to help, but this might get you started:
You can override the save method on the Transaction model like so:
class Transaction(models.Model):
...
def save(self, *args, **kwargs):
# add / create family group if it is missing:
if not self.family_group:
self.family_group = <the Family_group instance>
# add / create family member if it is missing:
if not self.family_group.family_member_set.all()
self.family_group.add([<the Family_member instance>])
self.family_group.save()
return super(Transaction, self).save(*args, **kwargs)

Django access to product total price through order model

I want to get each product's total price in all orders which I mean how much each product sold in all orders. What Query should I write in views.py to display this matter in html?
this is my models.py:
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
description = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('Pending', 'Pending'),
('Shipping', 'Shipping'),
('Delivered', 'Delivered'),
)
# order will remain after customer deleted
customer = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(Product, null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
note = models.CharField(max_length=200, null=True)
def __str__(self):
return self.product.name
and this is my views.py:
def home(request):
products = Product.objects.all()
orders = Order.objects.all()
total_order_prices = Order.objects.aggregate(Sum('price'))
orders.products = Product.objects.all().aggregate(Sum('price'))
context = {'orders':orders, 'products':products,'total_order_prices': total_order_prices }
return render(request, 'account/home.html', context)
Morez!
What I recommend is defining a foreign key to Order() in the Product(). Doing so would allow you to get related objects much more easily, as shown here.
All you would have to do is products = order.product_set.
Hope it helps!

One To Many and models

i am trying to build my first project, a CRM website to handle orders and inventory.
and i got stuck, i was able to link orders to customer.
but when i try to build order that contain multi items. for some reason i didn't find a way to do it.
hope you can assist me.
so I have User>>Order>>Multi Items.
questions:
1) does the best practice here is just use ForeignKey ?
this my model's code:
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
def date_createdview(self):
return self.date_created.strftime('%B %d %Y')
class Product(models.Model):
CATEGORY = (
('General', 'General'),
('SmartHome', 'SmartHome'),
('Software', 'Software'),
('Mobile', 'Mobile'),
)
name = models.CharField(verbose_name='שם', max_length=200, null=True)
price = models.FloatField(verbose_name='מחיר', null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY, verbose_name='קטגוריה')
description = models.CharField(max_length=200, null=True, verbose_name='מלל חופשי')
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Order(models.Model):
STATUS = (
('New', 'New'),
('Work in progress', 'Work in progress'),
('completed', 'completed'),
)
customer = models.ForeignKey(Customer, null=True, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def date_createdview(self):
return self.date_created.strftime('%d/%m/%Y')
class OrderItem(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
order = models.ForeignKey(Order, null=True, on_delete=models.CASCADE)
quantity = models.IntegerField(null=True)
2)how should I build my views or forms?
i want to make it dynamic, when i enter the order i can insert items and see the new item get add to a list of the items in the order.
how can save the order number and add new items?
this is my product view, it's working. I can add new products.
#login_required(login_url="login")
def products(request):
form = ProductForm(request.POST or None)
if form.is_valid():
form.save()
products = Product.objects.all()
context = {'form': form, 'products': products}
return render(request, 'accounts/products.html', context)
hope you can direct me to the right place.
thank you!
if form.is_valid():
order = get_object_or_404(Order, id=id)
instance = form.save(commit=False)
instance.order=order
instance.save()
just need to do:
commit=False
and then link the order.

Categories