How to add to cart in DRF - django

I am trying to create order:
models.py:
class OrderItem(models.Model):
image_number = models.CharField(max_length=20)
title = models.CharField(max_length=20)
image_size = models.CharField(max_length=50)
file_type = models.CharField(max_length=20)
price = models.CharField(max_length=50)
def __str__(self):
return self.title
class Order(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
def __str__(self):
return str(self.user)
serializers.py:
class AddtocartSerializers(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ['image_number','title','image_size','file_type','price']
class CartSerializers(serializers.ModelSerializer):
class Meta:
model = Order
fields = ['item',
'start_date',
'ordered_date'
]
views.py:
class AddtocartView(viewsets.ModelViewSet):
authentication_classes = []
permission_classes = []
pagination_class = None
queryset=OrderItem
serializer_class = AddtocartSerializers
class CartView(viewsets.ModelViewSet):
authentication_classes = []
permission_classes = []
pagination_class = None
queryset=Order.objects.all()
serializer_class = CartSerializers
urls.py: api endpint
path('addtocart/',views.AddtocartView.as_view({'get':'list'}),name='addtocart'),
path('cart/',views.CartView.as_view({'get':'list'}),name='cart'),
I am confused here; should I create new order objects from serialzers or views?

You should override the created method on the AddtocartSerializers to add the order item to the order.
You can see more information about it here: https://www.django-rest-framework.org/api-guide/serializers/#writing-create-methods-for-nested-representations

Related

KeyError: 'id' in django rest framework when trying to use update_or_create() method

I am trying to update the OrderItem model using update_or_create() method. OrderItem model is related to the Order model with many to one relationship ie with a Foreignkey.
I am trying to query the orderitem object using id and update the related fields using default as you can see, but got this error.
My models:
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
ordered_date = models.DateTimeField(auto_now_add=True)
ordered = models.BooleanField(default=False)
total_price = models.CharField(max_length=50,blank=True,null=True)
#billing_details = models.OneToOneField('BillingDetails',on_delete=models.CASCADE,null=True,blank=True,related_name="order")
def __str__(self):
return self.user.email
class Meta:
verbose_name_plural = "Orders"
ordering = ('-id',)
class OrderItem(models.Model):
#user = models.ForeignKey(User,on_delete=models.CASCADE, blank=True)
order = models.ForeignKey(Order,on_delete=models.CASCADE, blank=True,null=True,related_name='order_items')
item = models.ForeignKey(Product, on_delete=models.CASCADE,blank=True, null=True)
order_variants = models.ForeignKey(Variants,on_delete=models.CASCADE,blank=True,null=True)
quantity = models.IntegerField(default=1)
ORDER_STATUS = (
('To_Ship', 'To Ship',),
('Shipped', 'Shipped',),
('Delivered', 'Delivered',),
('Cancelled', 'Cancelled',),
)
order_item_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')
My view:
class UpdateOrderView(UpdateAPIView):
permission_classes = [AllowAny]
queryset = Order.objects.all()
serializer_class = OrderUpdateSerializer
My serializers:
class OrderUpdateSerializer(serializers.ModelSerializer):
order_items = OrderItemUpdateSerializer(many=True)
billing_details = BillingDetailsSerializer()
class Meta:
model = Order
fields = ['id','ordered','order_status','order_items','billing_details']
def update(self, instance, validated_data):
instance.order_status = validated_data.get('order_status')
instance.ordered = validated_data.get('ordered')
#billing_details_logic
billing_details_data = validated_data.pop('billing_details',None)
if billing_details_data is not None:
instance.billing_details.address = billing_details_data['address']
instance.billing_details.save()
#order_items_logic
instance.save()
order_items_data = validated_data.pop('order_items')
# print(order_items_data)
#instance.order_items.clear()
for order_items_data in order_items_data:
oi, created = OrderItem.objects.update_or_create(
id= order_items_data['id'],
defaults={
'quantity' : order_items_data['quantity'],
'order_item_status': order_items_data['order_item_status']
}
)
super().update(instance,validated_data)
return oi
Updated serializer:
for order_item_data in order_items_data:
oi, created = instance.order_items.update_or_create(
id= order_item_data['id'],
defaults={
'quantity' : order_item_data['quantity'],
'order_item_status': order_item_data['order_item_status']
}
)
The order_items data are sent like this.
order_items_data is a list.
Then you iterate over it with the same variable name.
for order_items_data in order_items_data:
Just rename it to something like
for order_data in order_items_data:
and there will be an id in your order_data.
I wasn't getting the id on the OrderedDict also, so I've added a id = serializers.IntegerField(required=False) on the serializer and put that id into the update_or_create method:
for obj in data:
Model.objects.update_or_create(
pk=obj.get('id', None), ...
)

checking if a certain many to many foreign key is present on django-polymorphic models

So in order to create an object model, I have to first see if a supplier has a relation of type many to many from BusinessModel, WarehouseModel or StoreModel to in a django-polymorphic
My main idea is to check if BusinessModel, which is connected to Order through BusinessOrderModel, StoreModel, which is connected to Order through StoreOrderModel or WarehouseModel which is connected directly to Order, have FKs on a many to many relationship going to the article that we want to order through a POST request.
class ArticleModel(models.Model):
id = models.AutoField(primary_key=True)
code = models.IntegerField(unique=True)
description = models.TextField()
def __str__(self):
return str(self.code)
class OrderModel(models.Model):
id = models.AutoField(primary_key=True)
order_to = models.ForeignKey('OrderToModel', on_delete=models.CASCADE)
article = models.ForeignKey('ArticleModel', on_delete=models.CASCADE)
quantity= models.IntegerField()
class OrderToModel(PolymorphicModel):
id = models.AutoField(primary_key=True)
class WarehouseModel(OrderToModel):
warehouse_num = models.IntegerField(unique=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return "Warehouse"+ str(self.warehouse_num)
class StoreOrderModel(OrderToModel):
reference = models.IntegerField(unique=True)
store_num = models.ForeignKey('StoreModel', on_delete=models.CASCADE)
def __str__(self):
return str(self.reference)
class StoreModel(models.Model):
store_num = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return str(self.store_num)
class BusinessOrderModel(OrderToModel):
reference = models.IntegerField(unique=True)
business_num = models.ForeignKey('BusinessModel', on_delete=models.CASCADE)
def __str__(self):
return str(self.reference)
class BusinessModel(models.Model):
Business_num = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
address = models.TextField()
articles = models.ManyToManyField(ArticleModel)
def __str__(self):
return str(self.Business_num)
Here's my serializers:
class WarehouseSerializer(serializers.ModelSerializer):
class Meta:
model = WarehouseModel
fields = ('id', 'warehouse_num')
class StoreOrderSerializer(serializers.ModelSerializer):
class Meta:
model = StoreOrderModel
fields = ('id', 'reference', 'store_num')
class DetailSerializer(serializers.ModelSerializer):
class Meta:
model = DetailModel
fields = ('id', 'detail')
class BusinessOrderSerializer(serializers.ModelSerializer):
details = DetailSerializer(many=True, read_only=True)
class Meta:
model = BusinessOrderModel
fields = ('reference', 'business_num','details')
class OrderToPolymorphicSerializer(PolymorphicSerializer):
model_serializer_mapping = {
WarehouseModel: WarehouseSerializer,
StoreOrderModel: StoreOrderSerializer,
BusinessOrderModel: BusinessOrderSerializer
}
and here's my view:
class OrderCreateView(generics.CreateAPIView):
queryset = OrderModel.objects.all()
serializer_class = OrderCreateSerializer

django-rest-framework aggregated sum fields

serializers.py
class BuildPlanNewSerializer(serializers.ModelSerializer):
StatusName = serializers.CharField(source='BuildPlanStatusID.StatusName', read_only=True)
# build_plan_list_new = serializers.StringRelatedField(many=True, read_only=True)
total_build_plan_list = serializers.SerializerMethodField()
def get_total_build_plan_list(self, language):
return language.build_plan_list_new.count()
class Meta:
model = BuildPlanNew
fields = ('StatusName', 'total_build_plan_list')
class BuildPlanListNewSerializer(serializers.ModelSerializer):
sku = serializers.CharField(source='ProductID.sku', read_only=True)
class Meta:
model = BuildPlanListNew
fields = "__all__"
models.py
class BuildPlanNew(models.Model):
emp_id = models.ForeignKey(Employee, on_delete=models.CASCADE, null=True, blank=True)
StartDate = models.DateTimeField()
EndDate = models.DateTimeField()
BuildPlanStatusID = models.ForeignKey(GlobalStatus, on_delete=models.CASCADE)
class BuildPlanListNew(models.Model):
BuildPlanID = models.ForeignKey(BuildPlanNew, on_delete=models.CASCADE, null=True, blank=True, related_name="build_plan_list_new")
ProductID = models.ForeignKey(Product, on_delete=models.CASCADE)
TotalPlanQty = models.IntegerField()
TotalBuiltQty = models.IntegerField())
QtyPreset = models.IntegerField(default=None, max_length=256)
Objective = models.IntegerField(default=None, max_length=256)
QtyAssigned = models.IntegerField(default=None, max_length=256)
view.py
class BuildPlanNewView(viewsets.ModelViewSet):
queryset = BuildPlanNew.objects.all()
serializer_class = BuildPlanNewSerializer
class BuildPlanListNewView(viewsets.ModelViewSet):
queryset = BuildPlanListNew.objects.all()
serializer_class = BuildPlanListNewSerializer
Result i am getting:
[{
"StatusName": "1234",
"total_build_plan_list": 0
}]
Result i am expecting:
[{
"StatusName": "1234",
"total_build_plan_list": 0,
"QtyPreset_count":20,
"Objective_count":30
}]
Here i wants to fetch aggregated sum and average from foreign key table.
Need QtyPreset_count sum as QtyPreset_count
Need Objective_count sum as as Objective_count
I have shared my models views and serializers
Please have a look
just add fields to your serializer like you have done so far
from django.db.models import Sum, Avg
class BuildPlanNewSerializer(serializers.ModelSerializer):
StatusName = serializers.CharField(source='BuildPlanStatusID.StatusName', read_only=True)
# build_plan_list_new = serializers.StringRelatedField(many=True, read_only=True)
total_build_plan_list = serializers.SerializerMethodField()
QtyPreset_count = serializers.SerializerMethodField()
Objective_count = serializers.SerializerMethodField()
def get_total_build_plan_list(self, language):
return language.build_plan_list_new.count()
def get_QtyPreset_count(self, language):
return language.build_plan_list_new.aggregate(Sum('QtyPreset'))
# return language.build_plan_list_new.aggregate(Avg('QtyPreset')) if you need it's average
def get_Objective_count(self, language):
return language.build_plan_list_new.aggregate(Sum('Objective'))
class Meta:
model = BuildPlanNew
fields = ('StatusName', 'total_build_plan_list')

Django REST framework: how to combine the same type of model

How to combine many models in one query set so that it would be possible to use HyperlinkedModelSerializer using pagination?
I need to connect many models with the same fields.
That's what I did, but it doesn’t suit me.:
#models.py
class Merketing(models.Model):
question = models.CharField(max_length=500, unique=True)
answer = models.CharField(max_length=500)
class Management(models.Model):
question = models.CharField(max_length=500, unique=True)
answer = models.CharField(max_length=500)
#serializers.py
class MerketingSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Merketing
fields = ['id','question', 'answer']
class ManagementSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Management
fields = ['id','question', 'answer']
class FiltersSerializers(serializers.Serializer):
model_1 = MerketingSerializer(read_only=True,many=True)
model_2 = ManagementSerializer(read_only=True,many=True)
#viesw.py
class MerketingViewSet(viewsets.ModelViewSet):
queryset = Merketing.objects.all().order_by('question')
serializer_class = MerketingSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
class ManagementViewSet(viewsets.ModelViewSet):
queryset = Management.objects.all().order_by('question')
serializer_class = ManagementSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
class FiltersView(APIView):
def get(self, request, *args, **kwargs):
filters = {}
filters['model_1'] = Merketing.objects.all().order_by('question')
filters['model_2'] = Management.objects.all().order_by('question')
serializer = FiltersSerializers(filters)
return Response (serializer.data, status=HTTP_200_OK)
Here is the solution to my problem !!!
class Fi2ViewSet(viewsets.ModelViewSet):
qs1 = Merketing.objects.all()
qs2 = Management.objects.all()
qs3= Macroeconom.objects.all()
qs4 = Kse.objects.all()
queryset = qs1.union(qs2,qs3,qs4).order_by('question')
serializer_class = Fi2Serializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [filters.SearchFilter]
search_fields = ['question']
serializers.py
class Fi2Serializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Merketing
fields = ['id','question', 'answer']

creating order from orderitem drf

i am trying to create order from orderitem. problem is how can i pass orderitem object to order.item field:
models.py:
class OrderItem(models.Model):
image_number = models.CharField(max_length=20)
title = models.CharField(max_length=20)
image_size = models.CharField(max_length=50)
file_type = models.CharField(max_length=20)
price = models.CharField(max_length=50)
def __str__(self):
return self.title
class Order(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, blank=True,null=True)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateField(auto_now_add=False,blank=True,null=True)
ordered = models.BooleanField(default=False)
def __str__(self):
return str(self.user)
serializers.py:
class AddtocartSerializers(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ['image_number','title','image_size','file_type','price']
class CartSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(queryset=CustomUser.objects.all())
items = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=OrderItem.objects.all(), required=True), required=True)
ordered_date = serializers.DateField()
class Meta:
model = Order
fields = ['user', 'items', 'ordered_date']
views.py:
class AddtocartView(generics.CreateAPIView):
authentication_classes = []
permission_classes = [IsAuthenticated]
pagination_class = None
queryset = OrderItem.objects.all()
serializer_class = AddtocartSerializers
def perform_create(self, serializer):
new_order_item = serializer.save()
user=CustomUser.objects.filter(id=self.request.user.id).first()
new_order = Order.objects.create(user=user)
new_order.items.add(new_order_item)
def __str__(self):
return self.user
class CartView(generics.ListAPIView):
authentication_classes = []
permission_classes = []
pagination_class = None
queryset=Order.objects.all()
serializer_class = CartSerializer
urls.py:
path('addtocart/',views.AddtocartView.as_view(),name='addtocart'),
path('cart/',views.CartView.as_view(),name='cart'),
customuser model:
class CustomUser(AbstractBaseUser, PermissionsMixin):
USER_TYPE_CHOICES = (
('user','user'),
('freelance_photographer', 'freelance_photographer'),
('photographer', 'photographer'),
('client', 'client'),
)
user_type = models.CharField(choices=USER_TYPE_CHOICES, null=True,max_length=20)
email = models.EmailField(max_length = 100, unique = True)
first_name = models.CharField(max_length = 100, null = True, blank = True)
last_name = models.CharField(max_length = 100, null = True, blank = True)
is_staff = models.BooleanField(default = False)
is_superuser = models.BooleanField(default = False)
is_active = models.BooleanField(default = True)
last_login = models.DateTimeField(null = True, blank = True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = "email"
EMAIL_FIELD = "email"
REQUIRED_FIELD = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
error:
Direct assignment to the forward side of a many-to-many set is prohibited. Use items.set() instead.
Is there any better way to create order?
You can create order with order item this way:
class AddtocartView(generics.CreateAPIView):
authentication_classes = []
permission_classes = [IsAuthenticated]
pagination_class = None
queryset = OrderItem.objects.all()
serializer_class = AddtocartSerializers
def perform_create(self, serializer):
new_order_item = serializer.save()
new_order = Order.objects.create()
new_order.items.add(new_order_item)