Reputation: 45
So, this here is a dirty production-level code, and I am stuck at this. I am designing a Return API but I am not good at this, help is much appreciated.
Traceback (most recent call last): File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\django\core\handlers\exception.py", line 55, in inner response = get_response(request) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view return view_func(*args, **kwargs) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\rest_framework\viewsets.py", line 125, in view return self.dispatch(request, *args, **kwargs) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\rest_framework\views.py", line 509, in dispatch response = self.handle_exception(exc) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\rest_framework\views.py", line 469, in handle_exception self.raise_uncaught_exception(exc) File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception raise exc File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\rest_framework\views.py", line 506, in dispatch response = handler(request, *args, **kwargs) File "C:\Users\Abdul\Documents\storefront\accounts\views.py", line 115, in create order = serializer.save() File "C:\Users\Abdul\Documents\storefront\accounts\serializers.py", line 155, in save refund.order = order_id File "C:\Users\Abdul\.virtualenvs\storefront\lib\site-packages\django\db\models\fields\related_descriptors.py", line 235, in __set__ raise ValueError( ValueError: Cannot assign "1": "Refund.order" must be a "Order" instance.
views.py
:
class RefundViewSet(ModelViewSet):
http_method_names = ['get', 'post', 'delete', 'head', 'options']
def get_permissions(self):
if self.request.method == 'POST':
return [IsAdminUser()]
return [IsAuthenticated()]
def create(self, request, *args, **kwargs):
serializer = RefundOrderSerializer(
data=request.data,
context={'user_id': self.request.user.id})
serializer.is_valid(raise_exception=True)
order = serializer.save()
serializer = OrderSerializer(order)
return Response(serializer.data)
def get_serializer_class(self):
if self.request.method == 'POST':
return RefundOrderSerializer
return OrderSerializer
def get_queryset(self):
user = self.request.user
if user.is_staff:
return Order.objects.all()
customer_id = Customer.objects.only('id').get(user_id=user.id)
return Order.objects.filter(customer_id=customer_id)
I don't think this part has any problems.
serializers.py
:
class RefundOrderSerializer(serializers.Serializer):
order_id = serializers.IntegerField()
###validator methods to ensure that only a customer with an order can request a refund.###
def validated_order_id(self, order_id):
if not Order.objects.filter(pk=order_id).exist():
raise serializers.ValidationError('No order with given id was found.')
return order_id
def save(self, **kwargs):
with transaction.atomic():
order_id = self.validated_data['order_id']
message = serializers.CharField(max_length=500)
email = serializers.EmailField()
refund = Refund()
refund.order = order_id
refund.reason = message
refund.email = email
refund.save()
return refund
This is the Problem Part
models.py
:
class Customer(models.Model):
MEMBERSHIP_BRONZE = 'B'
MEMBERSHIP_SILVER = 'S'
MEMBERSHIP_GOLD = 'G'
MEMBERSHIP_DIAMOND = 'D'
MEMBERSHIP_CHOICES = [
(MEMBERSHIP_BRONZE, 'BRONZE'),
(MEMBERSHIP_SILVER, 'SILVER'),
(MEMBERSHIP_GOLD, 'GOLD'),
(MEMBERSHIP_DIAMOND, 'DIAMOND')
]
phone = models.CharField(max_length=255)
birth_date = models.DateField(null=True, blank=True)
customer_subscription = models.CharField(max_length=1, choices=MEMBERSHIP_CHOICES, default=MEMBERSHIP_BRONZE)
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
company = models.CharField(max_length=255)
def __str__(self):
return f'{self.user.first_name} {self.user.last_name} {self.customer_subscription}'
@admin.display(ordering='user__first_name')
def first_name(self):
return self.user.first_name
@admin.display(ordering='user__last_name')
def last_name(self):
return self.user.last_name
class Meta:
ordering = ['user__first_name', 'user__last_name']
permissions = [
('view_history', 'Can view history')
]
class Order(models.Model):
ORDER_STATUS_PENDING = 'P'
ORDER_STATUS_FAILED = 'F'
ORDER_STATUS_COMPLETED = 'C'
ORDER_STATUS_CANCELLED = 'D'
ORDER_STATUS_CHOICES = [
(ORDER_STATUS_PENDING, 'PENDING'),
(ORDER_STATUS_CANCELLED, 'CANCELLED'),
(ORDER_STATUS_FAILED, 'FAILED'),
(ORDER_STATUS_COMPLETED, 'COMPLETED')
]
id = models.IntegerField(primary_key=True)
placed_at = models.DateTimeField(auto_now_add=True)
order_status = models.CharField(max_length=1, choices=ORDER_STATUS_CHOICES, default=ORDER_STATUS_PENDING)
customer = models.ForeignKey(Customer, on_delete=models.PROTECT, null=True)
refund_requested = models.BooleanField(default=False)
refund_granted = models.BooleanField(default=False)
class Meta:
permissions = [
('cancel_order', 'Can Cancel Order')
]
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.PROTECT, related_name='items')
product = models.ForeignKey(Product, on_delete=models.PROTECT, related_name="orderitems")
quantity = models.PositiveSmallIntegerField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.product)
class Cart(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4)
created_at = models.DateTimeField(auto_now_add=True)
class CartItem(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, related_name='items')
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveSmallIntegerField()
class Meta:
unique_together = [['cart', 'product']]
class Refund(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='refunds')
reason = models.TextField()
accepted = models.BooleanField(default=False)
email = models.EmailField()
def __str__(self):
return f"{self.pk}"
Used this code as an example from justdjango. just the Refund part.
I tried a lot of techniques to no avail with different results. Even advices are appreciated.
Upvotes: 0
Views: 174
Reputation: 3504
Assign an Order
instance rather than the order ID to refund.order
. You'll need to query for the matching order.
This is indicated in the Refund
model by
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='refunds')
and in the error
`ValueError: Cannot assign "1": "Refund.order" must be a "Order" instance.`
class RefundOrderSerializer(serializers.Serializer):
order_id = serializers.IntegerField()
###validator methods to ensure that only a customer with an order can request a refund.###
def validated_order_id(self, order_id):
if not Order.objects.filter(pk=order_id).exist():
raise serializers.ValidationError('No order with given id was found.')
return order_id
def save(self, **kwargs):
with transaction.atomic():
order_id = self.validated_data['order_id']
message = serializers.CharField(max_length=500)
email = serializers.EmailField()
refund = Refund()
# Solution in context
refund.order = Order.objects.get(pk=order_id)
refund.reason = message
refund.email = email
refund.save()
return refund
Upvotes: 1