It's a little clogged, so make a note.
In django-rest-framework (hereafter DRF), conversion between Json and Model is performed via an object called ModelSerializer. When editing and registering the value received by API, returning a record that does not exist in the table, processing the data and converting it to Json, a method is often added to Serializer.
Also, in DRF, when token authentication is performed, the user instance is stored in the request object. If you pass a user instance to Serializer, the value of the relation destination can be automatically entered, so there are many usage scenes.
model
The prerequisite Visitor model is as follows.
import uuid
from django.db import models
from api.models import AppUser
from web.models import AdminUser
class Visitor(models.Model):
class Meta:
db_table = "visitor"
verbose_name_plural = 'Visitor'
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
parent_user = models.ForeignKey(AdminUser,
on_delete=models.CASCADE,
related_name='visitor')
name = models.CharField(max_length=50)
email = models.EmailField(max_length=255, null=True, blank=True)
company = models.CharField(max_length=50, blank=True, null=True)
memo = models.TextField(blank=True, null=True, max_length=300)
visit_count = models.PositiveIntegerField(default=0)
created_by = models.ForeignKey(AppUser,
on_delete=models.SET_NULL,
null=True, blank=True,
related_name='visitor')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
serializer
The serializer creates fields associated with the model. To change the value arbitrarily, override it with SerializerMethodField ()
.
The field defined by SerializerMethodField ()
calls the methodget_ <field name>
and stores the return value.
The method of get_ <field name>
has ʻinstance` as an argument.
Therefore, I thought that it would be passed here when API authentication was performed, but it seems that the instance itself created at the time of Creation is passed here.
(If you use this, you can automatically create the data of the relation destination.)
from rest_framework.serializers import ModelSerializer, SerializerMethodField
class VisitorCreateSerializer(ModelSerializer):
created_by = SerializerMethodField()
parent_user = SerializerMethodField()
class Meta:
model = Visitor
read_only_fields = (
'pk',
'created_at',
'created_by',
)
fields = (
'pk',
'parent_user',
'created_at',
'name',
'email',
'company',
'memo',
'updated_at',
)
def get_created_by(self, instance):
"""The sending user is created_Stored in by"""
return str(instance.pk)
def get_parent_user(self, instance):
"""parent_Automatically store user"""
return str(instance.parent_user.pk)
ViewSet
In View, there is a part that instantiates Serializer, so if you pass user to instance here, it's OK. This time I wanted to separate the serializer only for create, so I overridden the create method and specified the Serializer.
# DRF
from rest_framework import status, viewsets
from rest_framework.permissions import IsAuthenticated
from .serializers import VisitorSerializer, VisitorCreateSerializer
from .models import Visitor
from utils.auth.authentication import APIAuthentication
from rest_framework.response import Response
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer #Serializer used other than create
queryset = Visitor.objects.all()
authentication_classes = (APIAuthentication,)
permission_classes = (IsAuthenticated,)
def get_queryset(self):
#When API authentication is performed,user instance is request.Stored in user.
admin = self.request.user.parent_user
qs = Visitor.objects.filter(parent_user=admin)
return qs
#Override create method
def create(self, request, *args, **kwargs):
#Request to Serializer.If you pass user, get_<field name>Instance is passed to the method
serializer = VisitorCreateSerializer(instance=request.user, data=request.data)
#From here on down
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Recommended Posts