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 makemigrationspython 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