Home > Software engineering >  Django Rest Framework to receive specific product by field
Django Rest Framework to receive specific product by field

Time:08-08

I am currently making an API to return JSON for a product.

Currently using Django rest framework, I have successfully implemented the API to view all products via

path/api/products

to show a JSON of all products:

HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "url": "http://127.0.0.1:8000/api/products/1/",
        "id": 1,
        "brand": "Mars",
        "name": "Barres",
        "barcode": 5000159366168,
        "category": "Snacks, Snacks sucrés, Cacao et dérivés, Confiseries, Barres, Confiseries chocolatées, Barres chocolatées, Barres chocolatées au caramel",
        "allergens": "gluten,milk,soybeans",
        "weight": 540.0,
        "quantity": 1,
        "footprint": 2.28655779803366e-06,
        "perishable": false
    },
    {
        "url": "http://127.0.0.1:8000/api/products/2/",
        "id": 2,
        "brand": "Twix",
        "name": "Twix",
        "barcode": 5000159366267,
        "category": "Snacks, Snacks sucrés, Confiseries, Barres",
        "allergens": "gluten,nuts",
        "weight": 600.0,
        "quantity": 1,
        "footprint": 0.0,
        "perishable": false
    },
    {
        "url": "http://127.0.0.1:8000/api/products/3/",
        "id": 3,
        "brand": "Twix",
        "name": "Twix salted caramel",
        "barcode": 5000159528955,
        "category": "Biscuits et gâteaux, Biscuit chocolat",
        "allergens": "caramel, choclate, wheat",
        "weight": 46.0,
        "quantity": 1,
        "footprint": 0.0,
        "perishable": false
    }
]

However, I would like to be able to receive the JSON object of only one product by barcode:

for example

path/api/products/5000159366168 or path/api/products/?barcode=5000159366168

to return only the product that matches the barcode:

{
        "url": "http://127.0.0.1:8000/api/products/1/",
        "id": 1,
        "brand": "Mars",
        "name": "Barres",
        "barcode": 5000159366168,
        "category": "Snacks, Snacks sucrés, Cacao et dérivés, Confiseries, Barres, Confiseries chocolatées, Barres chocolatées, Barres chocolatées au caramel",
        "allergens": "gluten,milk,soybeans",
        "weight": 540.0,
        "quantity": 1,
        "footprint": 2.28655779803366e-06,
        "perishable": false
    }

Here is my code:

my views.py:

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

my serializers.py:

from app1.models import Product
from rest_framework import serializers
class ProductSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Product
        fields = ["url","id", "brand", "name", "barcode","category","allergens", "weight", "quantity", "footprint","perishable"]

my urls.py:

router = routers.DefaultRouter()
router.register(r'products', views.ProductViewSet)


urlpatterns = [
    ...
    path('api/', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

CodePudding user response:

You need to override get_queryset() method to filter your data with your barcode or any other filter you want.

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def get_queryset(self):
        super(ProductViewSet, self).get_queryset()
        barcode= request.query_params.get('barcode', None)
        queryset = Product.objects.all()
        if barcode:
            queryset = Product.objects.filter(barcode=barcode)
        return queryset

Notice: How I added if condition for barcode that only if barcode variable have some data in it, filter it otherwise simply return the normal queryset.

CodePudding user response:

With help from Asim Ejaz
Here is my working View.py class

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    

    def get_queryset(self):
        super(ProductViewSet, self).get_queryset()
        barcode = self.request.query_params.get('barcode', None)
        print("Barcode = ", barcode)
        print(self)
        queryset = Product.objects.all()
        if barcode:
            queryset = Product.objects.filter(barcode=barcode)
        return queryset

Notice: barcode = self.request
as request is not previously defined

If you too run into this error, ensure the request is typed in properly, in this case it should be, http://127.0.0.1:8000/api/products/?barcode=5000159366168

  • Related