My models.py:
class CartModel(models.Model):
CART_STATUS = (
('n', 'Новая'),
('o', 'Заказана'),
('d', 'Удалена'),
)
status = models.CharField(
max_length=1, choices=CART_STATUS, blank=True, default='n')
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(
UserModel, on_delete=models.CASCADE, related_name='cart', verbose_name='Принадлежит')
created_at = models.DateTimeField(
auto_now_add=True, verbose_name="Дата создания")
class Meta:
verbose_name = "Корзина"
verbose_name_plural = "Корзина"
ordering = ('-created_at',)
class CartItemModel(models.Model):
CARTITEM_STATUS = (
('a', 'Доступен'),
('n', 'Недоступен'),
('d', 'Удалён'),
)
status = models.CharField(
max_length=1, choices=CARTITEM_STATUS, blank=True, default='a')
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
product = models.ForeignKey(
ProductModel, on_delete=models.CASCADE, related_name='items', verbose_name="Продукт")
quantity = models.IntegerField(verbose_name="Количество")
cart = models.ForeignKey(
CartModel, on_delete=models.CASCADE, related_name='items', verbose_name="Корзина")
class Meta:
verbose_name = "Товар корзины"
verbose_name_plural = "Товары корзины"
class ProductModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=82, verbose_name='Товар')
category = models.ForeignKey(
ProductCategoryModel, on_delete=models.CASCADE, verbose_name='Категория', related_name='products')
description = models.TextField(max_length=256, verbose_name='Описание')
price = models.DecimalField(
max_digits=6, decimal_places=2, verbose_name='Цена')
general_quantity = models.IntegerField(verbose_name='Общее количество')
def __str__(self):
return self.title
class Meta:
verbose_name = "Товар"
verbose_name_plural = "Товары"
My serializers.py
class CartItemSerializer(serializers.ModelSerializer):
singe_item_price = serializers.SerializerMethodField('get_item_price')
def get_item_price(self, obj):
return obj.product.price
class Meta:
model = CartItemModel
exclude = ('cart',)
class CartSerializer(WritableNestedModelSerializer, serializers.ModelSerializer):
items = CartItemSerializer(many=True, required=True)
total_sum = serializers.SerializerMethodField('get_field_name')
def get_field_name(self, obj):
return sum([i.quantity*i.product.price for i in obj.items.all()])
class Meta:
model = CartModel
# exclude = ('user',)
fields = ('id', 'status', 'created_at', 'total_sum', 'items')
My views.py:
class CartAPIView(viewsets.ModelViewSet):
def perform_create(self, serializer):
serializer.validated_data['user'] = self.request.user
serializer.save()
queryset = CartModel.objects.all()
serializer_class = CartSerializer
class CartItemAPIView(viewsets.ModelViewSet):
queryset = CartModel.objects.all()
serializer_class = CartItemSerializer
So, if in Cart post-method quantity of item is more than general_quantity of product, status field have to change from default 'a' (availble) to 'n' (not available)
I tried override my CartAPIView perform_create function like this, but nothing changed:
class CartAPIView(viewsets.ModelViewSet):
def perform_create(self, serializer):
serializer.validated_data['user'] = self.request.user
for i in serializer.validated_data['items']:
if i['quantity'] > i['product'].general_quantity:
i['status'] = 'n'
serializer.save()
Swagger get cart: { "id": "7c399665-99f3-40cf-b638-89bdbe9d52a1", "status": "n", "created_at": "2023-03-14T20:02:53.763334+06:00", "total_sum": 4400, "items": [ { "id": "525543d8-dc3a-4e0c-adaf-153ed9ec4c06", "singe_item_price": 400, "status": "a", "quantity": 11, "product": "af00fa7f-ff76-4657-a33c-3e5cde1e8830" } ] }
General quantity is 10, but status still 'a'. Maybe it's better to make that logic in serializer, than in a view
You can modify your CartItemSerializer
to check the quantity and update the status in the validate()
method, like so:
class CartItemSerializer(serializers.ModelSerializer):
singe_item_price = serializers.SerializerMethodField('get_item_price')
def get_item_price(self, obj):
return obj.product.price
def validate(self, data):
"""
Check that quantity is not greater than general_quantity
"""
if data['quantity'] > data['product'].general_quantity:
data['status'] = 'n'
return data
class Meta:
model = CartItemModel
exclude = ('cart',)
Note: Models in django don't require
Model
to be added as suffix, so it is better to name the models asCartItem
,Cart
andProduct
fromCartItemModel
,CartModel
andProductModel
respectively.