TransWikia.com

How to filter a serializer manytomany field in djangorestframework

Stack Overflow Asked by abi crazieeee on January 17, 2021

I want to filter the manytomany field based on the current instance selected field[‘customer’]. I want the cart_items manytomany field to only contain the cart_items of the selected customer in cart API.

models.py

class Product(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    product_id = ShortUUIDField(unique=True, editable=False)
    name = models.CharField(max_length=100)
    # price = MoneyField(max_digits=14, decimal_places=2)
    price = models.DecimalField(max_digits=14, decimal_places=2)


class Customer(models.Model):
    customer_id = ShortUUIDField()
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
    name = models.CharField(max_length=255, blank=False)
    email = models.EmailField(unique=True)


class CartItems(models.Model):
    cart_items_id = ShortUUIDField()
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
    customer = models.ForeignKey(Customer, on_delete=models.DO_NOTHING)
    products = models.ForeignKey(Product, on_delete=models.DO_NOTHING)
    quantity = models.IntegerField(default=1)

    class Meta:
        unique_together = (
            ("customer", "user", "products"),
        )

class Cart(models.Model):
    cart_id = ShortUUIDField()
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
    customer = models.ForeignKey(Customer, on_delete=models.DO_NOTHING)
    cart_items = models.ManyToManyField(CartItems)

serializers.py

class CartSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Cart
        fields = '__all__'
        read_only_fields = ['user']

I have tried to use all of the things below. Any help would be appreciated.
Requirement:
The cart_items must contain items of the selected customer only.

class CartSerializer(serializers.ModelSerializer):
    """serializer for Product objects."""
    # authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True)

    # cart_items = serializers.PrimaryKeyRelatedField(queryset=models.CartItems.objects.filter(customer=self.context['request'].user), many=True)
    # cart_items = serializers.PrimaryKeyRelatedField(queryset=models.CartItems.objects.filter(user=2), many=True)
    # cart_items = CustomerFilteredPrimaryKeyRelatedField(many=True, source='user.Customer')

    # cart_items = serializers.PrimaryKeyRelatedField('get_cart')
    #
    # def get_cart(self, product):
    #     qs = models.CartItems.objects.filter(user=2)
    #     serializer = CartItemSerializer(instance=qs, many=True)
    #     return serializer.data

    class Meta:
        model = models.Cart
        fields = '__all__'
        read_only_fields = ['user']

One Answer

I'd suggest you have only one ForeignKey from CartItem and Cart model to django's User model. Two ForeignKeys (one to User, and another to Customer seems redundant). And in the view class, override the get_queryset to filter the querset on the user sending the request. If you're gonna keep customer as a field on the Cart model, fetch the customer object using the user object from request.

# views.py
class CartView(GenericAPIView, ListModelMixin):
    ... # Don't pass queryset attr here
    
    serializer_class = CartSerializer
    
    def get_queryset(self):
        user = self.request.user
        queryset = Cart.objects.prefetch_related('cart_items').filter(user=user)
        # If you aren't changing your model, you could get the customer as:
        # customer = Customer.objects.get(user=user)
        # queryset = Cart.objects.prefetch_related('cart_items').filter(customer=customer) 
        return queryset

EDIT: If what I understand is right, where you want to filter the queryset based on the customer, but the user in request is the merchant. I assume a query_param for the customer's id is being sent to the APIView, to filter the items.

try using this in get_queryset():

def get_queryset(self):
    customer_id = self.request.query_params.get('customer_id')
    # You could include the merchant user in the filter too, but I guess the customer filter would already narrow it down.
    queryset = Cart.objects.prefetch_related('cart_items__customer').filter(cart_items__customer_id=customer_id)
    return queryset

Answered by seanick on January 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP