Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

How to serialize an array of objects in Django


I am working with Django and REST Framework and I am trying to create a get function for one of my Views and running into an error. The basic idea is that I am creating a market which can have multiple shops. For each shop there can be many products. So, I am trying to query all those products which exist in one shop. Once I get all those products I want to send it to my serializer which will finally return it as a JSON object. I have been able to make it work for one product but it does not work for an array of products.

My Product model looks like this:

'''Product model to store the details of all the products'''
class Product(models.Model):

    # Define the fields of the product model
    name = models.CharField(max_length=100)
    price = models.IntegerField(default=0)
    quantity = models.IntegerField(default=0)
    description = models.CharField(max_length=200, default='', null=True, blank=True)
    image = models.ImageField(upload_to='uploads/images/products')
    category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)    # Foriegn key with Category Model
    store = models.ForeignKey(Store, on_delete=models.CASCADE, default=1)
    
    ''' Filter functions for the product model '''

    # Create a static method to retrieve all products from the database
    @staticmethod
    def get_all_products():

        # Return all products
        return Product.objects.all()

     # Filter the data by store ID:
    @staticmethod
    def get_all_products_by_store(store_id):

        # Check if store ID was passed
        if store_id:
            return Product.objects.filter(store=store_id)

The product serializer that I built is as follows:-

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

and the view that I created is below

class StoreView(generics.ListAPIView):
    """Store view which returns the store data as a Json file. 
    """

    # Define class variables 
    serializer_class = StoreSerializer

    # Manage a get request 
    def get(self, request):
        
        # Get storeid for filtering from the page
        store_id = request.GET.get('id')
       
        if store_id:
            queryset = Product.get_all_products_by_store(store_id)
            # queryset = Product.get_all_products_by_store(store_id)[0]
        else: 
            queryset = Product.get_all_products()
            # queryset = Product.get_all_products()[0]
            print("QUERYSET", queryset)
        
        return Response(ProductSerializer(queryset).data)

The above view gives me the following error

AttributeError at /market
Got AttributeError when attempting to get a value for field `name` on serializer `ProductSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'name'.

If instead queryset = Product.get_all_products_by_store(store_id), I use the line below it where I am only selecting the first option then I get the correct JSON response but if there multiple products then I am not able to serialize. How do I make it work?


Solution

  • I found the answer thanks to @yedpodtrzitko for giving the direction. I had to make two changes.

    1. Define queryset outside the function
    2. Pass many=True the the constructor of ModelSerializer
    class StoreView(generics.ListAPIView):
        """Store view which returns the store data as a Json file. 
        """
    
        # Define class variables 
        queryset = []
        serializer_class = StoreSerializer
    
        # Manage a get request 
        def get(self, request):
            
            # Get storeid for filtering from the page
            store_id = request.GET.get('id')
           
            if store_id:
                queryset = Product.get_all_products_by_store(store_id)
            else: 
                queryset = Product.get_all_products()
                print("QUERYSET", queryset)
            
            return Response(ProductSerializer(queryset, many = True).data)