Calculate the total amount of the cart in django rest framework - python

I'm new in django,I need calculate cart summa and I have these models:
class Customer(Base):
name = models.CharField(max_length=100)
phone_number = models.CharField(max_length=100, blank=True, null=True)
comments = models.CharField(max_length=255, blank=True, null=True)
class Cart(Base):
user = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="cart")
cart_number = models.CharField(max_length=500, default=increment_cart_number, null=True, blank=True)
total_summa = models.FloatField()
is_saved = models.BooleanField(default=False)
class Item(Base):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items')
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='product')
product_price = models.FloatField()
quantity = models.IntegerField(default=1)
I used generics view, Can i calculate cart summa like this
Bread 3x6000 = 18000
Milk 2x500 = 10000
Total_Summa = 28000
serializers.py
class CartCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Cart
fields = [ 'id', 'user', 'cart_number', 'create_date', 'total_summa', 'time', 'is_saved', ]
Could you help me please?

You can try the following using Sum and F expression
from django.db.models import F, Sum
cart.total_summa = Item.objects.filter(cart=cart).annotate(per_item_price=F('product_price')*F('quantity')).annotate(total_summa=Sum('per_item_price'))
Inside serializers you can use the following way
class CartCreateSerializer(serializers.ModelSerializer):
total_summa = serializers.SerializerMethodField("get_total_summa", read_only=True)
class Meta:
model = Cart
fields = [ 'id', 'user', 'cart_number', 'create_date', 'total_summa', 'time', 'is_saved']
def get_total_summa(self, obj):
return obj.items.annotate(per_item_price=F('product_price')*F('quantity')).annotate(total_summa=Sum('per_item_price')).values('total_summa')

Related

django Rest-framework serialize two tables

i have table "Books" with some fields, and i have table "Prices", each customer have self price, i don't know how get price for definitely client, how i must configure serializer? please, help me,
for example:
Book1 have 2 prices: Price1 - 100$, Price2 - 150$
Customer1 must buy with just Price1,
Customer2 must buy with just Price2
i need get for first Customer json like:
[{"code":"УТ-11111","author":"Пушкин","title":"Книга 1","price":"100"}]
for Second Customer
[{"code":"УТ-11111","author":"Пушкин","title":"Книга 1","price":"150"}]
.
class Book(models.Model):
title = models.CharField('Заголовок', max_length=250)
code = models.CharField('Код', primary_key=True, max_length=10)
isbn = models.CharField('ISBN', max_length=18, null=True, blank=True)
ean13 = models.CharField('EAN-13', max_length=13, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='Автор')
class PricesName(models.Model):
name = models.CharField('Вид цены', max_length=20)
def __str__(self):
return self.name
class Price(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
PricesName = models.ForeignKey(PricesName, on_delete=models.CASCADE)
price = models.FloatField()
def __str__(self):
return self.book.title+" "+self.PricesName.name
######### Serializers.py ##########################
class BookSerializer(serializers.ModelSerializer):
author = serializers.StringRelatedField()
class Meta:
model = Book
fields = #'__all__'
#### API.py ####
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = BookSerializer
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
filter_fields = ('title', 'author')
search_fields = ('title', 'author')
pagination_class = StandardResultsSetPagination
problem is solved
class BookSerializer(serializers.ModelSerializer):
prices = serializers.SerializerMethodField()
def get_prices(self, serializer):
#PriceName__id - price number allowed to current Customer
book_price = Price.objects.filter(book=serializer.code, PricesName__id=2).first()
try:
price = getattr(book_price, "price")
except:
price = 0
return price
class Meta:
model = Book
fields = "__all__"

TypeError at /cart/ 'Product' object is not subscriptable

I'm creating cart model in RESTful API project. For each product in request by using for statement I want to save each product, cauz in one request may appear more than one product in cart. Below is my
serializers.py:
from rest_framework import serializers
from main.serializers import ProductDetailsSerializer
from main.models import Cart, Product, CartProduct
# создаем сериализатор orderproduct
class CartProductSerializer(serializers.ModelSerializer):
class Meta:
model = CartProduct
fields = ('product', 'count')
class CartProductRepresentationSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(source='product.id')
title = serializers.CharField(source='product.title')
class Meta:
model = CartProduct
fields = ('id', 'title', 'price', 'count', 'product')
class AddProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('id')
class CartSerializer(serializers.ModelSerializer):
items = CartProductSerializer(many=True, write_only=True) # здесь мы добавляем этот продукт заказа
class Meta:
model = Cart
fields = ('count', 'items') # передаем все эти поля сюда
def get_total_cost(self, obj):
return obj.get_total_cost()
# здесь мы добавляем total cost (def get_total_cost(self. obj))
def create(self, validated_data):
request = self.context.get('request')
items = validated_data.pop('items')
cart = Cart.objects.create(**validated_data)
if request.user.is_authenticated:
cart.user = request.user
cart.save()
for product in items:
product = product['product']
# print(product)
product_id = request.GET.get('product')
CartProduct.objects.create(cart=cart, product_id=product_id, price=product.price, count=product['count'])
product.save()
def to_representation(self, instance):
representation = super().to_representation(instance)
representation['user'] = instance.user
representation['product'] = CartProductRepresentationSerializer(instance.products.all(), many=True, context=self.context).data
return representation
Here is the models. I create Cart and CartProduct for m2m field between Cart and Product
models.py
from django.db import models
from account.models import User
class Category(models.Model):
name = models.CharField(max_length=50 ,unique=True)
slug = models.SlugField(max_length=50 ,primary_key=True)
parent = models.ForeignKey('self', related_name='child', blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
if self.parent:
return f'{self.parent} -> {self.name}'
return self.name
class Product(models.Model):
category = models.ManyToManyField(Category)
title = models.CharField(max_length=250)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
author_id = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.title
class Comment(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
text = models.CharField(max_length=100)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return f"{self.author}: {self.text}"
class ProductImage(models.Model):
product = models.ForeignKey(Product, related_name='images', on_delete=models.CASCADE)
image = models.ImageField(upload_to='products', null=True, blank=True)
class Cart(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=255, blank=True, null=True, default=False)
user = models.ForeignKey(User, related_name="carts", on_delete=models.CASCADE, blank=True, null=True)
count = models.PositiveIntegerField(default=1)
class CartProduct(models.Model):
product = models.ForeignKey(Product, related_name='products', on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, related_name='cart', on_delete=models.CASCADE)
count = models.PositiveIntegerField(default=1)
price = models.DecimalField(max_digits=10, decimal_places=2, null=True)
Here is the views.py by using ModelViewSet I want to list all products in Cart
views.py
from rest_framework import viewsets
from cart.serializers import CartSerializer
from main.models import Cart
class CartViewSet(viewsets.ModelViewSet):
model = Cart
serializer_class = CartSerializer
def get_queryset(self,):
return Cart.objects.filter(user=self.request.user)

How to fetch data from other table django rest framework

I have a cartmodel, cartitem and offlinecheckout model. I want to display cartitem instead of cartmodel id, I want to display all the cartitem data which have cart_id = offlinecheckout cart_id. But I got this response.
I tried a lot but didn't get. Anybody will please help me.
views.py
class GetAPI(APIView):
def get(self, request, *args, **kwargs):
serializer = OfflineSerializer()
return Response(serializer.data)
models.py
class OfflineCheckOut(models.Model):
billing_name = models.CharField(max_length=254)
billing_phone_no = models.CharField(max_length=15)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
cart = models.ForeignKey('cart.CartModel', on_delete=models.CASCADE)
cartitem = models.ManyToManyField(CartItem, blank=True)
# time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.CASCADE)
address = models.ForeignKey('cart.CustomerAddress', on_delete=models.CASCADE)
status_choice = [
('0', 'Offline'),
('1', 'Online')
]
status = models.CharField(max_length=3, choices=status_choice, default=0)
# date = models.DateField()
date = models.DateField()
time_slot = models.ForeignKey('category.TimeSlot', on_delete=models.SET_NULL, null=True, blank=True)
order_id = models.CharField(max_length=254, blank=True)
# date = models.DateField()
razorpay_payment_id =models.CharField(max_length=254, blank=True)
razorpay_signature = models.CharField(max_length=254, blank=True)
paid = models.BooleanField(default=False)
service = models.ForeignKey('service.ServiceProvider', on_delete=models.SET_NULL, null=True, blank=True)
class CartModel(models.Model):
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
status_choice = [
('1', 'open'),
('2', 'closed')
]
status = models.CharField(max_length=2, choices=status_choice, default=1)
validated = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#property
def total_price(self):
return self.cartitem_set.aggregate(
total_price=Sum(F('quantity') * F('price'))
)['total_price'] or Decimal('0')
class CartItem(models.Model):
cart = models.ForeignKey('CartModel', on_delete=models.CASCADE)
user = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
service = models.ForeignKey('accounts.SubCategory', on_delete=models.CASCADE)
defects = models.ForeignKey('category.Defects', on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
price = models.IntegerField()
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now_add=True)
order_placed = models.BooleanField(default=False)
serializers.py
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cartitems = CartItemSerializer( read_only=True, many=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
You have to put them in a serializer for CartModel. Then OfflineSerializer will use that for cart field.
class CartModelSerializer(serializers.ModelSerializer):
cartitem_set = CartItemSerializer(read_only=True, many=True)
class Meta:
model = CartModel
fields = [
"cartitems_set",
# other fields here
]
class OfflineSerializer(serializers.ModelSerializer):
def total(self, obj):
return obj.total
total = serializers.IntegerField(read_only=True)
cart = CartModelSerializer(read_only=True)
class Meta:
model = OfflineCheckOut
fields = ['user', 'billing_name','billing_phone_no','cartitem', 'cartitems','cart', 'date', 'time_slot', 'address', 'total']
extra_fields = ['total', 'cartitems']
EDIT: Changed the related name serializer from cartlineitems_set to cartlineitem_set

django rest use relation model field in objects filter

hi i have 3 model name product, category, and categoryassin i want get 10 row from product object where category title is develop .
i did like this but it not work and i get error
class GetWebProductAPiView(APIView):
def get(self,request):
obj = Product.objects.filter(category__title = "develop")
serializer = ProductSerializer(instance=obj,many=True,context={'request': request})
return Response(serializer.data)
err:
Related Field got invalid lookup: title
how can in fix it?
this is my models
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)
title = models.CharField(max_length=200)
video_length = models.CharField(max_length=20, null=True, blank=True)
mini_description = models.CharField(max_length=1000, null=True, blank=True)
full_description = models.TextField(null=True, blank=True)
you_need = models.CharField(max_length=1000, null=True)
you_learn = models.CharField(max_length=2000, null=True)
price = models.CharField(max_length=50, null=True, blank=True)
free = models.BooleanField(default=False)
video_level = models.CharField(max_length=100, null=True, blank=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
publish = models.BooleanField(default=False)
draft = models.BooleanField(default=False)
slug = models.SlugField(allow_unicode=True, null=True, blank=True)
image = models.FileField(upload_to=upload_to_custom_p, null=True, blank=True)
class Category(models.Model):
parent_id = models.IntegerField(null=True, blank=True)
title = models.CharField(max_length=200)
class CategoryAssin(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, to_field='product_id', related_name='category')
cat_id = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='categoryid')
and this is related serilizers
class CategorySerializer(ModelSerializer):
class Meta:
model = Category
fields = [
'id',
'parent_id',
'title',
]
read_only_fields = ['id']
class CategoryAssinSeralizer(ModelSerializer):
product = serializers.SerializerMethodField()
def get_product(self, obj):
return obj.product.title
cat_name = serializers.SerializerMethodField()
def get_cat_name(self, obj):
return obj.cat_id.title
class Meta:
model = CategoryAssin
fields = [
'cat_id',
'cat_name',
'product',
]
read_only_fields = ['id']
# product
class ProductSerializer(ModelSerializer):
product_ratings = ProductRatingsSerializer(many=True, read_only=True)
product_discount = ProductDiscountControllSerializer(read_only=True)
product_video = ProductWithoutVideoSerializer(many=True, read_only=True)
author = serializers.SerializerMethodField()
base64_image = serializers.SerializerMethodField(read_only=True, allow_null=True)
def get_author(self, obj):
return obj.author.first_name + ' ' + obj.author.last_name
category = CategoryAssinSeralizer(many=True)
url = main_page_post
class Meta:
model = Product
fields = [
'product_id',
'url',
'author',
'title',
'mini_description',
'you_learn',
'you_need',
'full_description',
'price',
'free',
'video_level',
'video_length',
'created_date',
'updated_date',
'product_ratings',
'product_discount',
'product_video',
'image',
'slug',
'draft',
'publish',
'category',
'base64_image',
]
read_only_fields = ['product_id',
'created_date',
'updated_date',
'author',
'base64_image',
'product_ratings',
'product_discount',
]
Add this in you view:
prod_ids = CategoryAssin.objects.filter(cat_id__title='develop').values_list('product', flat=True)
obj = Product.objects.filter(product_id__in=prod_ids)

Categories and sub-categories in django

I have an entity of Products, category and sub-category. A category can have many products and also a category can have many sub-categories. For example a product called Iphone-4 can fall on smart phone subcategories of Electronics & Gadgets Category. Similiary samsung product can fall on same smart-phone sub-categories of Electronics&Gadgets Category. How could i show this relation effectively?
Here is what i did
class Category(models.Model):
name = models.CharField(max_length=80, null=True)
parent = models.ForeignKey('self', blank=True, null=True, related_name="children")
class Meta:
unique_together = ('parent',)
verbose_name = 'Category'
verbose_name_plural = 'Categories'
class Product(models.Model):
token = models.CharField(default=token_generator, max_length=20, unique=True, editable=False)
category = models.ForeignKey(Category)
company = models.ForeignKey(Company, related_name="company_product")
name = models.CharField(max_length=200, null=True)
model = models.CharField(max_length=100, blank=True, null=True)
specification = models.TextField(null=True, blank=True)
price = models.PositiveIntegerField(default=0)
admin.py
class ProductAdmin(admin.ModelAdmin):
list_select_related = ('category', 'company',)
class Meta:
model = Product
class CategoryAdmin(admin.ModelAdmin):
list_select_related = ('parent',)
list_display = ('name', 'parent', )
class Meta:
model = Category
This way in my admin, the categories and sub-categories are shown so vaguely. Category Electronics & Gadgets is shown multiple times. It is shown as per the number of sub-category that falls under this category.
Is this expected behavior or has to handle this other effective way?
Here is the code snippet to list nested Category and Sub-Category inside the Admin Panel. Please register the Category model in the admin.py of your application first.
# Category Model.
class Category(models.Model):
name = models.CharField(blank=False, max_length=200)
slug = models.SlugField(null=False)
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children', on_delete=models.SET_NULL)
class Meta:
db_table = "dj_categories"
# Add verbose name
verbose_name = 'Category'
verbose_name_plural = "Categories"
unique_together = ('slug', 'parent',)
def __str__(self):
return self.name

Categories