[PYTHON] django-rest-framework Changer dynamiquement les champs du sérialiseur

introduction

Lors de l'utilisation de serializer de django-rest-framework pour modifier dynamiquement les champs en réponse à une demande d'un client Vous pouvez revenir en utilisant la classe dans le guide officiel.

Il s'agit d'un exemple d'appel de l'ensemble de vues. Ici, seul le champ est modifié dynamiquement, mais en le combinant avec d'autres paramètres, le champ renvoyé peut être modifié de manière flexible.

Définition de classe dynamique

Utilisez les cours du guide officiel. https://www.django-rest-framework.org/api-guide/serializers/#dynamically-modifying-fields

from rest_framework import serializers


class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

Créer un modèle

C'est un modèle avec un code et un nom simples.

from uuid import uuid4
from django.db import models


class Customer(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
    code = models.CharField(verbose_name='code', help_text='code', max_length=10)
    name = models.CharField(verbose_name='Nom', help_text='Nom', max_length=50)

Créer un sérialiseur

class CustomerSerializer(DynamicFieldsModelSerializer):
    class Meta:
        model = Customer

        fields = (
            'id',
            'code',
            'name',
        )

Créer un ensemble de vues

Remplacez get_serializer avec la valeur de champ définie dans la chaîne de requête uniquement sur les requêtes GET Modifiez dynamiquement les colonnes pour obtenir.

from rest_framework import viewsets


class CustomerViewSet(viewsets.ModelViewSet):
    queryset = Customer.objects.all()
    serializer_class = CustomerSerializer

    def get_serializer(self, *args, **kwargs):
        if self.action == 'list':
            if 'fields[]' in self.request.query_params:
                kwargs['fields'] = self.request.query_params.getlist('fields[]')

        return super().get_serializer(*args, **kwargs)

Contrôle de fonctionnement

Si aucun champ n'est spécifié

curl -s -X GET "http://localhost:18000/api/customers/" -H "accept: application/json" | jq .
[
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx1",
    "code": "001",
    "name": "test1"
  },
  {
    "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx2",
    "code": "002",
    "name": "test2"
  }
]

Lorsque code, name est spécifié dans le champ

curl -s -X GET "http://localhost:18000/api/customers/?fields[]=code&fields[]=name" --globoff -H "accept: application/json" | jq .
[
  {
    "code": "001",
    "name": "test"
  },
  {
    "code": "002",
    "name": "test2"
  }
]

Recommended Posts

django-rest-framework Changer dynamiquement les champs du sérialiseur
Ajouter dynamiquement des champs de formulaire dans Django