I need to create double reverse queryset in Django, explained more in the code:
The models
class Book(models.Model):
date = models.DateTimeField(auto_now=True)
book_name = models.CharField(max_length=150)
book_level = models.ForeignKey(Level, on_delete=CASCADE)
book_subject = models.ForeignKey(Subject, on_delete=CASCADE)
book_teacher = models.ForeignKey(Teacher, on_delete=CASCADE, null=True, blank=True)
book_comission = models.DecimalField(max_digits=19, decimal_places=5, null=True, blank=True)
book_black_papers = models.IntegerField()
book_color_papers = models.IntegerField()
book_paper_cost = models.DecimalField(max_digits=19, decimal_places=5)
book_ink_cost = models.DecimalField(max_digits=19, decimal_places=5)
book_color_ink_cost = models.DecimalField(max_digits=19, decimal_places=5)
book_cover_cost = models.DecimalField(max_digits=19, decimal_places=5)
supplier = models.ForeignKey(Supplier, on_delete=CASCADE, null=True, blank=True)
book_total_cost = models.DecimalField(max_digits=19, decimal_places=5)
book_sell_price = models.DecimalField(max_digits=19, decimal_places=5)
viewed_by = models.ManyToManyField(User)
is_double_pages = models.BooleanField(default=False)
is_hidden = models.BooleanField(default=False)
image1 = ProcessedImageField(upload_to='book_image',
processors=[ResizeToFill(440, 262)],
format='JPEG',
options={'quality': 60}, blank=True, null=True)
image2 = ProcessedImageField(upload_to='book_image',
processors=[ResizeToFill(440, 262)],
format='JPEG',
options={'quality': 60}, blank=True, null=True)
image3 = ProcessedImageField(upload_to='book_image',
processors=[ResizeToFill(440, 262)],
format='JPEG',
options={'quality': 60}, blank=True, null=True)
image4 = ProcessedImageField(upload_to='book_image',
processors=[ResizeToFill(440, 262)],
format='JPEG',
options={'quality': 60}, blank=True, null=True)
published_online = models.BooleanField(default=False)
class VIPSellInvoice(models.Model):
ordered = 'تحت التنفيذ'
delivered = 'منتهية'
canceled = 'ملغاة'
invoice_choices = (
(ordered, 'تحت التنفيذ'),
(delivered, 'منتهية'),
(canceled, 'ملغاة'),
)
date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=PROTECT)
client = models.ForeignKey(VipClient, on_delete=PROTECT)
total = models.DecimalField(max_digits=19, decimal_places=5, default=0)
status = models.CharField(max_length=160, choices=invoice_choices)
delivery = models.ForeignKey(Delivery, on_delete=PROTECT, null=True, blank=True)
delivery_price = models.DecimalField(max_digits=19, decimal_places=5, default=0, null=True, blank=True)
delivery_notes = models.CharField(max_length=500, null=True, blank=True)
is_done = models.BooleanField(default=False)
class VipPriceList(models.Model):
book_name = models.ForeignKey(Book, on_delete=CASCADE)
book_price = models.DecimalField(max_digits=19, decimal_places=5)
book_client = models.ForeignKey(VipClient, on_delete=CASCADE)
book_client_comission = models.DecimalField(max_digits=19, decimal_places=5)
class VipClient(models.Model):
client_name = models.CharField(max_length=150)
client_address = models.CharField(max_length=150)
client_phone1 = models.CharField(max_length=20)
client_phone2 = models.CharField(max_length=20)
client_note = models.CharField(max_length=500, null=True, blank=True)
client_balance = models.DecimalField(max_digits=19, decimal_places=5, default=0)
client_commission = models.DecimalField(max_digits=19, decimal_places=5, default=0)
Am trying to get the VIPpricelists`` that belong to theclientthat belongs to the currentVip Invoicethen get theBook_set` in the final queryset so that I can deal with it.
here is howw i tried to call it in my views:
def vip_sellinvoice_add_books(request, pk):
current_vip_invoice = get_object_or_404(models.VIPSellInvoice, pk=pk)
test = current_vip_invoice.client.vippricelist_set.all().book_set.all()
context = {
'test': test,
}
return render(request, 'vip/vip_sell_invoice_add_books.html', context)
I get the error:
'QuerySet' object has no attribute 'book_set'
so, is it possible to create such a nested reverse querysets in Django or there is a simpler way to do it?
In that case, you usually query from the Book object itself, like:
Book.objects.filter(vippricelist__book_client__vIPsellinvoice=current_vip_invoice)
So here we query for Books for which there exists a VipPriceList object which has a book_client field that refers to a VipClient that is related to the current_vip_invoice).
Related
Here is my models.py. def str(self):return str(self.name) still won't change Product object (1) to the product name.
from cgi import print_exception
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, null=True, blank=True)
# image =
category = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
numReviews = models.IntegerField(null=True, blank=True, default=0)
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 str(self.name)
You should define __str__() method inside the class, also use f strings so:
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=200, null=True, blank=True)
# image =
category = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(
max_digits=7, decimal_places=2, null=True, blank=True)
numReviews = models.IntegerField(null=True, blank=True, default=0)
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 f"{self.name}"
if your __str__ not work and you receive a Object (1), it mean you use repr(obj). Therefore you should override __repr__ method.
def __repr__(self):
return f'{self.name}'
I'm working on a Django Ecommerce project where product has several attributes like. size, color( A single product can have multiple attributes with different size and color). No i'm trying to filter products using django_filters but unable to filter by its attributes.
Product Model:
class Product(models.Model):
variations = (
('None', 'None'),
('Size', 'Size'),
)
name = models.CharField(max_length=200, unique=True)
store = models.ManyToManyField(Store)
slug = models.SlugField(null=True, blank=True, unique=True, max_length=500)
sku = models.CharField(max_length=30, null=True)
tax = models.IntegerField(null=True, blank=True)
stock = models.CharField(max_length=10, null=True)
variations = models.CharField(choices=variations, max_length=20)
short_description = models.CharField(max_length=500, null=True)
details = RichTextUploadingField(null=True, blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
discounted_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
image = models.ImageField(upload_to='product/images', default='product.png', null=True,
blank=True)
image_one = models.ImageField(upload_to='product/images', null=True, blank=True)
image_two = models.ImageField(upload_to='product/images', null=True, blank=True)
image_three = models.ImageField(upload_to='product/images', null=True, blank=True)
image_four = models.ImageField(upload_to='product/images', null=True, blank=True)
image_five = models.ImageField(upload_to='product/images', null=True, blank=True)
tags = models.ManyToManyField(Tags)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True,
related_name='products')
status = models.CharField(max_length=20, choices=(('Active', 'Active'), ('Inactive',
'Inactive')))
brand = models.ForeignKey(Brand, on_delete=models.PROTECT, blank=True, null=True)
offer = models.ForeignKey(Offer, on_delete=models.CASCADE, null=True,
blank=True) # This is used only for filtration
Product attribute model
class ProductAttribute(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
size = models.ForeignKey(Size, on_delete=models.CASCADE, null=True, blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2, validators=
[MinValueValidator(1)])
discounted_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
stock = models.CharField(max_length=10, null=True)
The standard approach would be to define the attributes in the "Product" model. However, if you insist on doing this, the code will be:
filtered_ProductAttributes=ProductAttribute.objects.filter(size="12")
products=[filtered_ProductAttribute.product for filtered_ProductAttribute in filtered_ProductAttributes]
As you can see the code seems very inefficient, therefore, as was suggested in the beginning put the attributes in the "Product" model and you will have:
products=Product.objects.filter(size="12")
Refining your model will help you to filter.
With my experience following model approach will be more suitable:
class Attributes(models.Model):
name = models.CharField(max_length=50, default=None)
slug = models.SlugField(max_length=200, unique=True,null=True)
class AttributeTerms(models.Model):
name = models.CharField(max_length=50, blank =True)
attribute = models.ForeignKey(Attributes, on_delete=models.CASCADE)
class Products(models.Model):
name = models.CharField(max_length=250,null=True, blank=True,)
slug = models.SlugField(max_length=200, unique=True,null=True)
class ProductAttribute(models.Model):
product = models.ForeignKey(Products,on_delete=models.CASCADE, related_name='attributes', default=None)
attributes = models.ForeignKey(Attributes,on_delete=models.CASCADE, related_name='attributes', default=None)
values = models.ForeignKey(AttributeTerms, on_delete=models.CASCADE, related_name='attributes', default=None)
class ProductVariant(models.Model):
product = models.ForeignKey(Products,on_delete=models.CASCADE)
variant = models.ForeignKey(ProductAttribute,on_delete=models.CASCADE, null = True, default=None)
stock = models.IntegerField(default=None)
stock_threshold = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
sku = models.CharField(max_length= 250, default=None)
sale_price = models.DecimalField(max_digits=10, decimal_places=2)
I'm trying to get the object "Book" from prommotion. Book is a ForeignKey in "prommotion", and I filtered all the prommotions that are active. I need to get the "Book" object from the Prommotion if its active and return it.
(And I know promotion is spelled wrong)
Views:
class Book_PrommotionViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Prommotion.objects.filter(active=True)
serializer = PrommotionSerializer(queryset, many=True)
return Response(serializer.data, HTTP_200_OK)
Prommotion Model:
class Prommotion(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
precent = models.DecimalField(decimal_places=2, max_digits=255, null=True, blank=True)
active = models.BooleanField(default=False)
date_from = models.DateField()
date_to = models.DateField()
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True, blank=True)
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Prommotion'
verbose_name_plural = 'Prommotions'
Book Model:
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True, blank=True)
price = models.DecimalField(decimal_places=2, max_digits=255)
published = models.DateField()
edition = models.CharField(max_length=255)
isbn_code = models.CharField(max_length=255)
pages = models.IntegerField(blank=True, null=True, default=0)
description = models.TextField(null=True, blank=True)
cover = models.CharField(max_length=30, choices=Cover.choices(), default=None, null=True, blank=True)
genre = models.CharField(max_length=30, choices=Genre.choices(), default=None, null=True, blank=True)
language = models.CharField(max_length=30, choices=Language.choices(), default=None, null=True, blank=True)
format = models.CharField(max_length=30, choices=Format.choices(), default=None, null=True, blank=True)
publisher = models.CharField(max_length=30, choices=Publisher.choices(), default=None, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Meta:
verbose_name = 'Book'
verbose_name_plural = 'Books'
The first way to get all Books that are related to your active promotions is to extract the book ids from the queryset and pass it to a Book filter
active_promotions = Prommotion.objects.filter(active=True)
Book.objects.filter(id__in=active_promotions.values('book_id'))
Or simply filter books with active promotions by using the double underscore syntax to follow relationships
Book.objects.filter(prommotion__active=True).distinct()
I have two apps in Django project . one is "accounts" another is " Courses "
I have a model in accounts app
class Student(SoftDeleteModel):
user = models.OneToOneField(to=User, on_delete=models.CASCADE, related_name='student_info')
name = models.CharField(null=True, blank=True, max_length=250)
course_enrolled = models.ForeignKey(Courses,on_delete=models.CASCADE,blank=True)
trx_id = models.CharField(max_length=20)
date_of_birth = models.DateField(null=True, blank=True)
education_qualification = models.CharField(null=True, blank=True, max_length=250)
institution_name = models.CharField(null=True, blank=True, max_length=250)
image = models.ImageField(upload_to='photos/%y/%m/%d',null=True, blank=True)
address = models.CharField(null=True, blank=True, max_length=250)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.email
class Instractor(SoftDeleteModel):
user = models.OneToOneField(to=User, on_delete=models.CASCADE, related_name='instractor_info')
name = models.CharField(null=True, blank=True, max_length=250)
degination = models.CharField(null=True, blank=True, max_length=250)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
This is model for accounts
and Course Model is:
from accounts.models import *
class Courses(models.Model):
title = models.CharField(max_length=200,blank=True,null=True)
image = models.ImageField(null=True,upload_to="photos/course/")
category = models.ForeignKey(Category,on_delete=models.CASCADE)
instractor = models.ForeignKey(Instractor, on_delete=models.CASCADE,blank=True)
total_student_enrolled = models.IntegerField(null=True,blank=True)
price = models.IntegerField(blank=True,null=True)
course_length_in_hour = models.IntegerField(blank=True,null=True)
course_length_in_weeks = models.IntegerField(blank=True,null=True)
programming_language = models.CharField(max_length=500,null=True,blank=True)
course_requirements = models.TextField()
course_description = models.TextField()
what_you_will_learn = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateField(auto_now_add=True)
is_published = models.BooleanField(default=False)
slug = models.SlugField(null = False, blank = True)
def __str__(self):
return self.title
I have import courses.model but it showing that Instractor not Defined. But if i remove
course_enrolled = models.ForeignKey(Courses,on_delete=models.CASCADE,blank=True)
course_enrolled field from accounts model the error is not showing :/
I don't get what is the problem is .
Error Message is :
instractor = models.ForeignKey(Instractor, on_delete=models.CASCADE,blank=True)
NameError: name 'Instractor' is not define
You need to put the model name in quotes when defining a FK:
instractor = models.ForeignKey("accounts.Instractor", on_delete=models.CASCADE,blank=True)
Cant actually find anything like what i am trying to do with wanting to use case statements and left joins using DRF Django Rest Framework, yes this could be done on the front end of the project i am working on but id rather not have to let the front end potentially sending 100s of requests when loading a product list for example.
Nothing i can really add to this but i have tried many different ways of doing the below
SELECT
p.itemno,
CASE
WHEN cp.price IS NULL THEN p.HighSell
ELSE cp.price
END AS price
FROM
api_product AS p
LEFT JOIN
api_customerprices AS cp ON p.itemno = cp.itemno
AND cp.customerno = 'Examplecust'
WHERE
p.FreeStock > 0
or restockDate > '1900-01-01'
Here Are my models:
class Product(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
itemno = models.CharField(max_length=100)
description = models.TextField(null=True)
colour = models.CharField(max_length=100, null=True)
manufacturerCode = models.CharField(max_length = 100, null=True)
RRP = models.DecimalField(max_digits=6, decimal_places=2, null=True)
SSP = models.DecimalField(max_digits=6, decimal_places=2,null=True)
FreeStock = models.IntegerField(null=True)
ItemSpec1 = models.CharField(max_length=100, null=True)
ItemSpec2 = models.CharField(max_length=100, null=True)
ItemSpec3 = models.CharField(max_length=100, null=True)
ItemSpec4 = models.CharField(max_length=100, null=True)
ItemSpec5 = models.CharField(max_length=100, null=True)
ItemSpec6 = models.CharField(max_length=100, null=True)
ItemSpec7 = models.CharField(max_length=100, null=True)
ItemSpec8 = models.CharField(max_length=100, null=True)
ItemSpec9 = models.CharField(max_length=100, null=True)
ItemSpec10 = models.CharField(max_length=100, null=True)
TI = models.IntegerField(null=True)
HI = models.IntegerField(null=True)
Item_Height = models.DecimalField(max_digits=6, decimal_places=2, null=True)
Item_Length = models.DecimalField(max_digits=6, decimal_places=2, null=True)
Item_Width = models.DecimalField(max_digits=6, decimal_places=2, null=True)
ProductPaging_Height = models.DecimalField(max_digits=6, decimal_places=2, null=True)
ProductPaging_Length = models.DecimalField(max_digits=6, decimal_places=2, null=True)
ProductPaging_Width = models.DecimalField(max_digits=6, decimal_places=2, null=True)
CartonHeight = models.DecimalField(max_digits=6, decimal_places=2, null=True)
CartonLength = models.DecimalField(max_digits=6, decimal_places=2, null=True)
CartonWidth = models.DecimalField(max_digits=6, decimal_places=2, null=True)
palletQty = models.IntegerField(null=True)
cartonQty = models.IntegerField(null=True)
restockDate = models.DateField(null=True)
IPG = models.CharField(max_length=100, null=True)
CatalogueTheme = models.CharField(max_length=100, null=True)
Analysis2 = models.CharField(max_length=100, null=True)
Electrical_or_Housewares = models.CharField(max_length=100, null=True)
HighSell = models.DecimalField(max_digits=6, decimal_places=2, null=True)
Analysis1 = models.CharField(max_length=100, null=True)
Image = models.TextField(null=True, blank=True)
MarketingText = models.TextField(null=True, blank=True)
SearchTerms = models.TextField(null=True, blank=True)
ItemVariant = models.CharField(max_length=100)
Categories = models.CharField(max_length=249, null=True)
def __str__(self):
return self.itemno
class CustomerPrices(models.Model):
customerNo = models.CharField(max_length=20)
itemno = models.CharField(max_length=20)
price = models.DecimalField(max_digits=6, decimal_places=2)
startDate = models.DateField()
endDate = models.DateField()
def __str__(self):
return self.customerNo
Here are my Serializers
class OauthProdListSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = (
'id',
'itemno',
'description',
'colour',
'RRP',
'SSP',
'manufacturerCode',
'FreeStock',
'restockDate',
'Image',
'HighSell',
'ItemVariant',
'Categories'
)
class OCustomerPricesSerializer(serializers.ModelSerializer):
class Meta:
model = CustomerPrices
fields = (
'id',
'customerNo',
'itemno',
'price'
)
Found a way of performing what i wanted, turned out i was missing knowledge on the SerializerMethodField() method, once i found out that i got it pretty quickly.
class ProdListSerializer(ModelSerializer):
price = SerializerMethodField()
class Meta:
model = Product
fields = [
'id',
'itemno',
'description',
'colour',
'RRP',
'SSP',
'manufacturerCode',
'FreeStock',
'restockDate',
'Image',
'ItemVariant',
'Categories',
'price'
]
def get_price(self, obj):
itemno = obj.itemno
customerNo = self._context['view'].request.query_params.get('customerNo', '')
if customerNo:
customerPrice = CustomerPrices.objects.filter(
Q(customerNo=customerNo) &
Q(itemno=itemno)
).values('price').first()
if customerPrice:
return customerPrice
else:
return Product.objects.filter(itemno=itemno).values('HighSell').first()
else:
return Product.objects.filter(itemno=itemno).values('HighSell').first()
I am just writing this off the top of my head so it will take some effort on your part to get it working.
You do not have a relationship between your Product and CustomerPrices. You will either need to add a Foreignkey between the two tables directly or, you will need to add an intermediate table with foreignkeys between them.
Your query will be something like:
Q is a django query object - see Complex lookups with Q objects
results = CustomerPrices.objects.filter(
Q(itemno__FreeStock__gt=0) | Q(itemno__restockDate__gt='1900-0-01'),
customerno='Examplecust'
)
# Your case statement can be handled in your code logic:
def case_statement(result):
if not result.price:
return result.HighSell
return result.price
I am not exactly sure what you mean, but you can get the SQL for all the tables in an app by running this command:
python manage.py sqlall your_app
or you want to convert sql to django use :
Person.objects.raw('your_sql_query')