Django Rest Framework CRUD operations
Serializing Many To Many Relationship table
api/models.py
 xxxxxxxxxxfrom django.db import modelsclass Material(models.Model):    name = models.CharField(max_length=120)    price = models.FloatField()    def __str__(self):        return self.nameclass Product(models.Model):    name = models.CharField(max_length=120)    materials = models.ManyToManyField(Material, through='MaterialProduct')    def __str__(self):        return self.nameclass MaterialProduct(models.Model):    """ many to many intermediate table """    material = models.ForeignKey(Material, on_delete=models.CASCADE)    product = models.ForeignKey(Product, on_delete=models.CASCADE)    material_ratio = models.FloatField()- Apply models to the database: - python manage.py makemigrations
- python manage.py migrate
 
api/serializers.py
 xxxxxxxxxxfrom rest_framework import serializersfrom .models import Product, Material, MaterialProductclass MaterialSerializer(serializers.ModelSerializer):    class Meta:        model = Material        fields = '__all__'class MaterialProductSerializer(serializers.ModelSerializer):    material = MaterialSerializer()    class Meta:        model = MaterialProduct        fields = '__all__'class ProductSerializer(serializers.ModelSerializer):    # To get materials which are associated with a product    materials = serializers.SerializerMethodField()    class Meta:        model = Product        fields = '__all__'        depth = 1    def get_materials(self, obj):        query_set = MaterialProduct.objects.filter(product=obj)        return [MaterialProductSerializer(item).data for item in query_set]api/routes.py
 xxxxxxxxxxfrom rest_framework.views import APIViewfrom rest_framework.response import Responsefrom polls.serializers import MaterialSerializer, ProductSerializer, MaterialProductSerializerfrom polls.models import Product, Material, MaterialProductclass ProductList(APIView):    def get(self, request):        products = Product.objects.all()        serializer = ProductSerializer(products, many=True)        return Response(serializer.data)api/urls.py
 xxxxxxxxxxfrom django.urls import pathfrom polls.routes import ProductListurlpatterns = [    path('api/products', ProductList.as_view(), name='products'),]project/urls.py
 xxxxxxxxxxfrom django.contrib import adminfrom django.urls import path, includeurlpatterns = [    path('admin/', admin.site.urls),    path('',include('api.urls')),]- GET request to http://127.0.0.1:8000/api/products
- Returned data:
 xxxxxxxxxx[    {        "id": 1,        "materials": [            {                "id": 1,                "material": {                    "id": 3,                    "name": "material3",                    "price": 15.0                },                "material_ratio": 20.0,                "product": 1            },            {                "id": 2,                "material": {                    "id": 6,                    "name": "material6",                    "price": 30.0                },                "material_ratio": 80.0,                "product": 1            }        ],        "name": "product44"    },    {        "id": 2,        "materials": [],        "name": "product66"    },    {        "id": 3,        "materials": [            {                "id": 6,                "material": {                    "id": 1,                    "name": "material1",                    "price": 5.0                },                "material_ratio": 5.0,                "product": 3            },            {                "id": 7,                "material": {                    "id": 2,                    "name": "material2",                    "price": 10.0                },                "material_ratio": 15.0,                "product": 3            },            {                "id": 8,                "material": {                    "id": 4,                    "name": "material4",                    "price": 20.0                },                "material_ratio": 25.0,                "product": 3            },            {                "id": 9,                "material": {                    "id": 8,                    "name": "material8",                    "price": 50.0                },                "material_ratio": 45.0,                "product": 3            },            {                "id": 10,                "material": {                    "id": 10,                    "name": "material10",                    "price": 1000.0                },                "material_ratio": 10.0,                "product": 3            }        ],        "name": "product100"    },    {        "id": 4,        "materials": [],        "name": "product200"    },    {        "id": 5,        "materials": [            {                "id": 3,                "material": {                    "id": 2,                    "name": "material2",                    "price": 10.0                },                "material_ratio": 30.0,                "product": 5            },            {                "id": 4,                "material": {                    "id": 4,                    "name": "material4",                    "price": 20.0                },                "material_ratio": 40.0,                "product": 5            },            {                "id": 5,                "material": {                    "id": 8,                    "name": "material8",                    "price": 50.0                },                "material_ratio": 30.0,                "product": 5            }        ],        "name": "product300"    },    {        "id": 6,        "materials": [            {                "id": 11,                "material": {                    "id": 5,                    "name": "material5",                    "price": 25.0                },                "material_ratio": 100.0,                "product": 6            }        ],        "name": "product444"    }]Product Detail
api/routes.py
 xxxxxxxxxx...from django.shortcuts import get_object_or_404class ProductDetail(APIView):    def get(self, request, pk):        product = get_object_or_404(Product, pk=pk)        serializer = ProductSerializer(product)        return Response(serializer.data)api/urls.py
 xxxxxxxxxxfrom polls.routes import ProductList, ProductDetailpath('api/products/<int:pk>', ProductDetail.as_view(), name='product-detail'),- GET request to the http://127.0.0.1:8000/api/products/5
- Returned data:
 xxxxxxxxxx{    "id": 5,    "materials": [        {            "id": 3,            "material": {                "id": 2,                "name": "material2",                "price": 10.0            },            "material_ratio": 30.0,            "product": 5        },        {            "id": 4,            "material": {                "id": 4,                "name": "material4",                "price": 20.0            },            "material_ratio": 40.0,            "product": 5        },        {            "id": 5,            "material": {                "id": 8,                "name": "material8",                "price": 50.0            },            "material_ratio": 30.0,            "product": 5        }    ],    "name": "product300"}Create Product | POST request
api/routes.py
 xxxxxxxxxxfrom rest_framework import statusclass ProductList(APIView):    def get(self, request):        #...     def post(self, request, format=None):        serializer = ProductSerializer(data=request.data)        if serializer.is_valid():            serializer.save()            return Response(serializer.data, status=status.HTTP_201_CREATED)        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)- POST request to the http://127.0.0.1:8000/api/products
- data : {"id":integer_number, "name":"new product"}
- returned data:
 xxxxxxxxxx{    "id": 7,    "materials": [],    "name": "new_product"}Update Product | PUT request
api/routes.py
 xxxxxxxxxxclass ProductDetail(APIView):    def get(self, request, pk):        #...            def put(self, request, pk, format=None):        product = get_object_or_404(Product, pk=pk)        serializer = ProductSerializer(product, data=request.data)        if serializer.is_valid():            serializer.save()            return Response(serializer.data)        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)- PUT request to the http://127.0.0.1:8000/api/products/6
- data: {"name":"product444updated"}
- returned data:
 xxxxxxxxxx{    "id": 6,    "materials": [        {            "id": 11,            "material": {                "id": 5,                "name": "material5",                "price": 25.0            },            "material_ratio": 100.0,            "product": 6        }    ],    "name": "product444updated"}Delete Request
api/routes.py
 xxxxxxxxxxclass ProductDetail(APIView):    def get(self, request, pk):        #...    def put(self, request, pk, format=None):        #...    def delete(self, request, pk, format=None):        product = get_object_or_404(Product, pk=pk)        product.delete()        return Response(status=status.HTTP_204_NO_CONTENT)- DELETE request : curl -X DELETE http://127.0.0.1:8000/api/products/6
Product Material List
api/routes.py
 xxxxxxxxxxclass ProductList(APIView):    #...class ProductDetail(APIView):    #...class ProductMaterialList(APIView):    def get(self, request, pk):        mp = MaterialProduct.objects.filter(product=pk)        materials = []        for item in mp:            materials.append(item.material)        serializer = MaterialSerializer(materials, many=True)        return Response(serializer.data)api/urls.py
 xxxxxxxxxxfrom api.routes import ProductList, ProductDetail, ProductMaterialListurlpattern = [    path('api/products', ProductList.as_view(), name='products'),    path('api/products/<int:pk>', ProductDetail.as_view(), name='product-detail'),     path('api/products/<int:pk>/materials', ProductMaterialList.as_view(), name='product-material-list'),]- GET request to the http://127.0.0.1:8000/api/products/1/materials-returned data:
 xxxxxxxxxx[    {        "id": 3,        "name": "material3",        "price": 15.0    },    {        "id": 6,        "name": "material6",        "price": 30.0    }]Product's multiple Material Update | bulk update
api/serializers.py
 xxxxxxxxxxclass MaterialListSerializer(serializers.ListSerializer):    def update(self, instance, validated_data):        material_mapping = {material.id: material for material in instance}        data_mapping = {item['id']: item for item in validated_data}        result = []        for material_id, data in data_mapping.items():            material = material_mapping.get(material_id, None)            if material is not None:                result.append(self.child.update(material, data))        return result    class MaterialSerializer(serializers.ModelSerializer):    id = serializers.IntegerField()    class Meta:        model = Material        fields = '__all__'        list_serializer_class = MaterialListSerializerapi/routes.py
 xxxxxxxxxxclass ProductMaterialList(APIView):    def get(self, request, pk):        #...    def put(self, request, pk, format=None):        mp = MaterialProduct.objects.filter(product=pk)        materials = []        for item in mp:            materials.append(item.material)        serializer = MaterialSerializer(materials, request.data, many=True)        if serializer.is_valid():            serializer.save()            return Response(serializer.data)        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)- PUT request to the http://127.0.0.1:8000/api/products/1/materials
- data :
 xxxxxxxxxx[ {"id" : 3,  "name" : "material3_UPDATED" , "price" : 200 }, {"id" : 6 ,  "name" : "material6_UPDATED",  "price" : 600  }]- returned_data:
 xxxxxxxxxx[    {        "id": 3,        "name": "material3_UPDATED",        "price": 200.0    },    {        "id": 6,        "name": "material6_UPDATED",        "price": 600.0    }]
Yorumlar