Django-Rest-Framework CRUD operations using Generic Views
In this article, we will briefly see how to implement CRUD operations in Django-Rest-Framework using generic class-based views.
Models
In this example, we'll be using only one model, which is very simple.
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=50)
price = models.DecimalField(max_digits=5, decimal_places=2)
def get_discounted_price(self, percent):
return "%.2f" % (float(self.price) * (1 - percent / 100))
def __str__(self):
return self.name
So, we have a table called Product
with two columns in it name
, and price
, also we have a method to calculate a new discounted price called get_discounted_price
.
Serializers
Again, we have only one serializer in this example.
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
sale_price = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Product
fields = ["id", "name", "price", "sale_price"]
def get_sale_price(self, obj):
return obj.get_discounted_price(5)
Notice that, we have a Serializer Method Field, we discussed that in the previous article. In short, we used it to add a new field in the data coming through API to the client side, and that field is sale_price
.
Look at the previous article for a little more information on that.
URLs
Before we work on views, let's add the URLs first, because they are very simple, and easy to do.
from django.urls import path
from .views import (
ProductDetailAPIView,
ProductListCreateAPIView,
ProductUpdateAPIView,
ProductDeleteAPIView,
)
urlpatterns = [
path("", ProductListCreateAPIView.as_view()),
path("<int:pk>/update/", ProductUpdateAPIView.as_view()),
path("<int:pk>/delete/", ProductDeleteAPIView.as_view()),
path("<int:pk>/", ProductDetailAPIView.as_view()),
]
Also, we have the base URLs file, which includes this file with prefix api/products/
.
Views
Finally, here we will add the views.
First, here are a few import statements, just in case!
from rest_framework import generics
from .models import Product
from .serializers import ProductSerializer
ListCreateAPIView
This API View is used for both, List and Create.
List the objects if the request method is GET
, and create an object if the request method is POST
.
class ProductListCreateAPIView(generics.ListCreateAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def perform_create(self, serializer):
# print(serializer.validated_data)
return super().perform_create(serializer)
Play around with it to know more stuff.
Here, we do not really need perform_create
method, as it is not doing anything, but you can customize the view through that method easily.
And let's see this in action in the browsable API below.
Here it shows the list of the objects we have in the database.
And there is a form below to create a new object.
UpdateAPIView
Here's our update API view.
class ProductUpdateAPIView(generics.UpdateAPIView):
queryset = Product.objects.all() # or get_queryset
serializer_class = ProductSerializer
def perform_update(self, serializer):
# we can play around with serializer here
name = serializer.validated_data.get("name")
if "x" not in name:
name = "x" + name
serializer.validated_data["name"] = name
return super().perform_update(serializer)
Here, we have a method called perform_update
, which we do not really need, but we can use it to customize the view a little bit, for example, we are adding x
in the beginning of the name if it is not in the name.
So, if we update the name to PS5, it will save it as xPS5.
DestroyAPIView
Deleting stuff is very simple, and most of the code is the same.
class ProductDeleteAPIView(generics.DestroyAPIView):
queryset = Product.objects.all() # or get_queryset
serializer_class = ProductSerializer
def perform_destroy(self, instance):
return super().perform_destroy(instance)
Here, we have a method perform_destroy
, which is doing nothing, but if we'd like, we can do some checks before deleting the stuff.
Let's delete the product with id=3
.
The product is deleted!
RetriveAPIView
This view is simply used to get an object through the lookup field (like primary key pk
).
class ProductDetailAPIView(generics.RetrieveAPIView):
queryset = Product.objects.all() # or get_queryset
# lookup_field = "pk" # default queryset lookup
serializer_class = ProductSerializer
It simply shows details for a single object.
That's all for now, next time we will see some more advance stuff.
So, grab a coffee or two for the next article.
Thanks!