web-dev-qa-db-fra.com

Quel est l'avantage d'utiliser un HyperlinkedModelSerializer dans DRF?

En référence à ce lien , j'ai vu de nombreux exemples d'utilisation d'un HyperlinkedModelSerializer dans Django Rest Framework. Ça dit:

La classe HyperlinkedModelSerializer est similaire à ModelSerializer classe sauf qu’elle utilise des hyperliens pour représenter les relations, plutôt que des clés primaires.

Ma question est la suivante: quel est le cas d'utilisation/l'avantage de leur utilisation par rapport à un modèle standard de sérialiseur? 

34
Tim S.

Comme dans la citation que vous avez incluse, la seule différence est que les clés primaires et étrangères sont représentées par des URL qui pointent vers ces ressources, plutôt que sur les valeurs de clés réelles. 

L'avantage est que vous ne devrez pas créer d'URL de ressources dans votre interface lorsque vous souhaitez récupérer des objets liés.

Une autre chose est entièrement les représentations imbriquées qui vous permettent d’aligner des objets liés dans la sortie de votre sérialiseur. Ceci peut être combiné à la fois avec ModelSerializer et HyperlinkedModelSerializer lorsque vous pensez qu'il est plus pratique pour le consommateur d'API d'avoir immédiatement des éléments liés au lieu de faire des demandes supplémentaires pour les récupérer.

Les représentations imbriquées peuvent être implémentées via l'option Meta.depth ou en utilisant le sérialiseur du modèle associé au lieu d'une RelatedField.

Comme @xleon l'a dit dans son commentaire, l'utilisation d'URL comme clés facilite la compréhension de votre API par les autres développeurs.

27
Ivan

Nous devons implémenter les relations entre les entités dans la conception des API Web . Il y a plusieurs façons de le faire (comme mentionné dans la documentation DRF):

  • Utilisation de clés primaires. 
  • Utilisation de liens hypertextes entre entités. 
  • Utilisation d'un champ d'identification unique sur l'entité associée. 
  • Utilisation de la représentation de chaîne par défaut de l'entité associée. 
  • Imbrication de l'entité associée dans la représentation parente. 
  • Une autre représentation personnalisée

HyperlinkedModelSerializer présente les différences suivantes par rapport à ModelSerializer:

  • Il n'inclut pas le champ id par défaut.
  • Il inclut un champ url, utilisant HyperlinkedIdentityField.
  • Les relations utilisent HyperlinkedRelatedField au lieu de PrimaryKeyRelatedField.

Un exemple simple:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'groups')


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ('url', 'name')

bash> http -a admin: yourpassword http://127.0.0.1:8000/users/

 "results": [
        {
            "email": "[email protected]",
            "groups": [
                "http://127.0.0.1:8000/groups/1/",
                "http://127.0.0.1:8000/groups/2/"
            ],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        }
    ]

Mais si tu changes 

class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('url', 'username', 'email', 'groups')

Le résultat sera:

   "results": [
        {
            "email": "[email protected]",
            "groups": [
                1,
                2
            ],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        }
    ]
20
Serjik

Il convient de noter que HyperlinkedModelSerializers présente un coût: si votre API prend en charge le filtrage ou la commande via des paramètres de requête dans l’URL, il est un peu plus difficile pour votre consommateur frontal d’utiliser les champs d’URL hyperliés pour la construction pk à partir de l'URL plutôt que d'avoir le pk directement disponible.

Par exemple, en supposant qu'un objet sur une route située à /api/objects/12/, le consommateur doit analyser le champ url pour extraire le 12 afin de construire une requête filtrant par cet objet sur un autre noeud final: /api/otherobjects/?object=12. Pas un gros problème, mais un inconvénient si vous envisagez de filtrer beaucoup.

1
Colton Hicks