[Django] Transmettez l'instance utilisateur authentifiée par l'API à ModelSerializer

C'est un peu bouché, alors prenez note.

environnement

À propos de ModelSerializer

Dans django-rest-framework (ci-après DRF), la conversion entre Json et Model est effectuée via un objet appelé ModelSerializer. Lors de l'édition et de l'enregistrement de la valeur reçue par l'API, du retour d'un enregistrement qui n'existe pas dans la table, du traitement des données et de leur conversion en Json, une méthode est souvent ajoutée au sérialiseur.

Dans DRF, lorsque l'authentification par jeton est effectuée, l'instance utilisateur est stockée dans l'objet de requête. Si vous transmettez une instance utilisateur à Serializer, la valeur de la destination de la relation peut être saisie automatiquement, il existe donc de nombreuses scènes d'utilisation.

model

Le modèle de visiteur prérequis est le suivant.

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 = 'Visiteur'

    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

Le sérialiseur crée des champs associés au modèle. Pour changer la valeur de manière arbitraire, remplacez-la par SerializerMethodField (). Le champ défini par SerializerMethodField () appelle la méthodeget_ <nom du champ>et stocke la valeur de retour.

La méthode de get_ <nom de champ> a ʻinstance` comme argument. Par conséquent, j'ai pensé qu'il serait passé ici lors de l'authentification API, mais il semble que l'instance elle-même créée au moment de la création soit passée ici. (Si vous l'utilisez, vous pouvez créer automatiquement les données de la destination de la relation.)

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):
        """L'utilisateur expéditeur est créé_Stocké par"""
        return str(instance.pk)

    def get_parent_user(self, instance):
        """parent_Enregistrer automatiquement l'utilisateur"""
        return str(instance.parent_user.pk)

ViewSet

Dans View, il y a une partie qui instancie Serializer, donc si vous passez l'utilisateur à l'instance ici, c'est OK. Cette fois, je voulais séparer le sérialiseur uniquement pour créer, j'ai donc remplacé la méthode create et spécifié le sérialiseur.

# 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 #Sérialiseur utilisé autre que créer
    queryset = Visitor.objects.all()

    authentication_classes = (APIAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        #Lorsque l'authentification API est effectuée,l'instance utilisateur est une demande.Stocké dans l'utilisateur.
        admin = self.request.user.parent_user
        qs = Visitor.objects.filter(parent_user=admin)
        return qs

    #Remplacer la méthode de création
    def create(self, request, *args, **kwargs):
        #Demande au sérialiseur.Si vous passez l'utilisateur, obtenez_<nom de domaine>L'instance passe à la méthode
        serializer = VisitorCreateSerializer(instance=request.user, data=request.data)
        #A partir d'ici vers le bas
        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

[Django] Transmettez l'instance utilisateur authentifiée par l'API à ModelSerializer
Passer les informations de connexion à afficher dans Django
Vous permet de sélectionner par nom à partir du nom d'utilisateur Django
Passer du texte à Django genericview
[pepper] Transmettez toutes les données JSON obtenues par requête python à la tablette.
Créer une API REST pour faire fonctionner dynamodb avec le Framework Django REST
Déployer le didacticiel Django sur IIS ①
[Django] Comment passer des valeurs directement des balises de modèle aux variables JavaScript
Comment vérifier la version de Django
Essayez de faire face à la somme partielle
J'ai essayé de toucher l'API COTOHA
Afficher les informations utilisateur, etc. dans le journal Django
Essayez d'accéder à l'API Spotify dans Django.
Créons-le en appliquant Protocol Buffer à l'API avec Serverless Framework.
[Django memo] Je souhaite définir à l'avance les informations de l'utilisateur connecté dans le formulaire.
Le format du message obtenu par Slack API est subtilement difficile à utiliser
J'ai essayé de passer le test G et la qualification E en m'entraînant à partir de 50