I am facing a problem while giving PUT request. url is : http://127.0.0.1:8000/api/v1/products/products/product-slug-9/ the error is :TypeError: django.db.models.manager.BaseManager._get_queryset_methods..create_method..manager_method() got multiple values for keyword argument 'product' models.py
class Product(models.Model):
"""
This is The Product table contining all product items.
"""
name = models.CharField(max_length=255)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
brand = models.ForeignKey(to='brands.BrandProfile',
on_delete=models.DO_NOTHING, related_name='brand_product')
# brand=models.CharField(max_length=30)
category = models.ForeignKey(
to='products.Category', on_delete=models.DO_NOTHING)
# sizes = ArrayField(
# models.CharField(max_length=10),
# )
# colors = ArrayField(
# models.CharField(max_length=56)
# )
is_available = models.BooleanField(default=True)
market_price = models.IntegerField()
selling_price = models.IntegerField()
description = models.TextField()
# stock_status , visibility_status
# product won't delete if category deleted, we have to do it manually.
visiblity = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-created_at',)
verbose_name = "Product"
verbose_name_plural = "Products"
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(str(self.name.lower()) str(uuid.uuid4()))
return super().save(*args, **kwargs)
def __str__(self):
return str(self.title)
@property
def discount_percent(self):
if self.selling_price:
discount_percent = 100 - \
(self.selling_price * 100) / self.market_price
return int(discount_percent)
return 0
class ProductImage(models.Model):
"""
The Product Image Table
"""
product = models.ForeignKey(
Product, on_delete=models.CASCADE, related_name='product_images')
image = models.ImageField(
upload_to=brand_product_image_file_path, blank=False, null=False)
product_color = models.CharField(max_length=56)
alt_text = models.CharField(max_length=24)
is_featured = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = "Product Image"
verbose_name_plural = "Product Images"
def __str__(self):
return str(self.alt_text)
views.py
class ProductModelViewset(viewsets.ModelViewSet):
serializer_class = ProductSerializer
parser_classes = [FormParser, MultiPartParser, JSONParser]
http_method_names = ['get', 'post', 'put', 'delete', 'head', 'options']
pagination_class = ProductPagination
lookup_field = "slug"
def get_serializer_class(self):
# if self.action
return super().get_serializer_class()
def get_queryset(self):
# queryset = Product.objects.filter(visiblity=True)
if self.request.user.is_authenticated and self.request.user.is_brand or self.request.user.is_staff:
queryset = Product.objects.all()
else:
queryset = Product.objects.filter(visiblity=True)
query = self.request.query_params.get('query', None)
ordering = self.request.query_params.get('ordering', None)
if query is not None:
queryset = queryset.filter(
Q(title__icontains=query) | Q(brand__brand_username__icontains=query)
)
if ordering is not None and ordering == "max_price":
queryset = queryset.order_by('-market_price')
if ordering is not None and ordering == "min_price":
queryset = queryset.order_by('market_price')
return queryset
def get_permissions(self):
if self.action == 'create':
self.permission_classes = [
IsAuthenticated, IsStaffOrIsBrandUser]
elif self.action in ['update', 'destroy']:
if self.request.user.is_authenticated and self.request.user.is_brand:
self.permission_classes = [
IsAuthenticated, IsBrandUser, AccessOwnProduct]
else:
self.permission_classes = [
IsAuthenticated, IsAdminUser]
else:
# self.permission_classes = [IsAuthenticatedOrReadOnly]
pass
return super(ProductModelViewset, self).get_permissions()
def update(self, request, *args, **kwargs):
return super().update(request, *args, **kwargs)
@action(detail=True, methods=['GET'], name='Related Products')
def related_products(self, request, slug):
product_queryset = Product.objects.filter(visiblity=True)
product = product_queryset.get(slug=slug)
category_products = product_queryset.filter(
category=product.category)
category_products_s = self.serializer_class(
category_products, many=True, context={'request': request})
res_context = {
"product": product.title,
"category": product.category.title,
"related_products": category_products_s.data
}
return Response(res_context, status=status.HTTP_200_OK)
serializers.py
class ProductImageSerializer(serializers.ModelSerializer):
# product=serializers.SerializerMethodField(required=False)
class Meta:
model = ProductImage
exclude = ('created_at', 'updated_at')
read_only_fields = ['id', ]
class ProductSerializer(serializers.ModelSerializer):
product_images = ProductImageSerializer(many=True)
discount_percent = serializers.SerializerMethodField()
category = serializers.SlugRelatedField(
queryset=Category.objects.all(),
slug_field='slug')
brand = serializers.SlugRelatedField(
queryset=BrandProfile.objects.all(),
slug_field='brand_username', required=False)
class Meta:
model = Product
fields = '__all__'
def get_discount_percent(self, obj):
return obj.discount_percent
def create(self, validated_data):
# print(validated_data)
product_images = validated_data.pop('product_images', None)
# print(f"product_images: {product_images}")
product = Product.objects.create(**validated_data)
product.brand=get_object_or_404(BrandProfile, email=self.context.get("request").user.email)
product.save()
# product.brand=self.context.brand_username
# product.update(brand=self.request.brand_username)
# product.save()
# print(self.context.get("request").user.email)
# print()
# for i in self.context.get("request").user:
# print(i)
# print(f"product: {product}")
for item in product_images:
item['product'] = product
# print(product)
# print(item)
# for i in item:
# print(i)
# print(ProductImageSerializer.create(self, **item))
# print(ProductImageSerializer.create(validated_data=item))
# instantiate class to be able parse self
serializer = ProductImageSerializer(data=item)
# check if data is correct
serializer.is_valid()
# run create method
# print(serializer.create(validated_data=serializer.validated_data))
# # ProductImageSerializer.create(**item)
# serializer = ProductImageSerializer(data=item)
# # check if data is correct
# print(f"serializer.data: {serializer.data}")
# print(f"serializer.is_valid: {serializer.is_valid()}")
# print(f"print(serializer.validated_data): {serializer.validated_data}")
# print(serializer.validated_data)
# run create method
# print(serializer.create(validated_data=serializer.data))
serializer.create(validated_data=serializer.data)
return product
# def create(self, validated_data):
# image_data = validated_data.pop('images', None)
# images = []
# for img in image_data:
# image = ProductImageSerializer.create(
# ProductImageSerializer(), validated_data=img)
# image.save()
# images.append(image)
# product = Product.objects.create(images=images, **validated_data)
# return product
def update(self, instance, validated_data):
product_images = validated_data.pop('product_images')
# print(product_images)
instance.name = validated_data.get('name', instance.name)
instance.title = validated_data.get('title', instance.title)
instance.brand = validated_data.get('brand', instance.brand)
instance.category = validated_data.get('category', instance.category)
# instance.sizes = validated_data.get('sizes', instance.sizes)
# instance.colors = validated_data.get('colors', instance.colors)
instance.is_available = validated_data.get(
'is_available', instance.is_available)
instance.market_price = validated_data.get(
'market_price', instance.market_price)
instance.selling_price = validated_data.get(
'selling_price', instance.selling_price)
instance.description = validated_data.get(
'description', instance.description)
instance.visiblity = validated_data.get(
'visiblity', instance.visiblity)
instance.save()
print("instance saved")
keep_images = []
for image in product_images:
# print(f"image: {image}")
if "id" in image.keys():
print("id here")
if ProductImage.objects.filter(id=image["id"]).exists():
print("image exists")
i = ProductImage.objects.get(id=image["id"])
i.image = image.get('image', i.image)
i.product_color = image.get(
'product_color', i.product_color)
i.alt_text = image.get('alt_text', i.alt_text)
i.is_featured = image.get('is_featured', i.is_featured)
i.save()
keep_images.append(i.id)
else:
continue
else:
print(f"new image: {image}")
print(instance)
i = ProductImage.objects.create(**image, product=instance)
keep_images.append(i.id)
print(keep_images)
for image in instance.images:
if image.id not in keep_images:
image.delete()
return instance
the error is like
Internal Server Error: /api/v1/products/products/product-slug-9/
Traceback (most recent call last):
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "D:\Django\merchbd\core-backend\app\products\views.py", line 124, in update
return super().update(request, *args, **kwargs)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\mixins.py", line 68, in update
self.perform_update(serializer)
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\mixins.py", line 78, in perform_update
serializer.save()
File "D:\Django\merchbd\core-backend\venv\lib\site-packages\rest_framework\serializers.py", line 200, in save
self.instance = self.update(self.instance, validated_data)
File "D:\Django\merchbd\core-backend\app\products\serializers.py", line 161, in update
i = ProductImage.objects.create(**image, product=instance)
TypeError: django.db.models.manager.BaseManager._get_queryset_methods.<locals>.create_method.<locals>.manager_method() got multiple values for keyword argument 'product'
what i should do now.
CodePudding user response:
There is another product
which is coming from image
.
you can
_ = image.pop('product')
i = ProductImage.objects.create(**image, product=instance)