2

J'applique une API REST en DRF avec ModelViewSet et ModelSerializer. Toutes mes API utilisent le format JSON et certains de mes modèles utilisent champ ChoiceField, comme ça:Retourne display_name dans ChoiceField

MyModel(models.Model): 
    KEY1 = 'Key1' 
    KEY2 = 'Key2' 
    ATTRIBUTE_CHOICES = (
     (KEY1, 'Label 1'), 
     (KEY2, 'Label 2')) 
    attribute = models.CharField(max_length=4, 
            choices=ATTRIBUTE_CHOICES, default=KEY1) 

Mon problème est que par défaut DRF renvoie toujours (et accepter) la clé de ces choix pour les messages JSON (voir here), mais je voudrais utiliser l'étiquette à la place, parce que je pense qu'il est plus cohérent et clair de ne pas savoir qui utilisera ces API. Toute suggestion?

Répondre

3

je trouve une solution possible, à savoir la définition de mon propre domaine comme suit:

class MyChoiceField(serializers.ChoiceField): 

    def to_representation(self, data): 
     if data not in self.choices.keys(): 
      self.fail('invalid_choice', input=data) 
     else: 
      return self.choices[data] 

    def to_internal_value(self, data): 
     for key, value in self.choices.items(): 
      if value == data: 
       return key 
     self.fail('invalid_choice', input=data) 

Il fonctionne de la même manière à ChoiceField, mais retourne et accepte les étiquettes au lieu des clés.

+0

Une raison pour laquelle vous économisez l'étiquette au lieu de la clé? – mariodev

+0

@mariodev Je ne sauvegarde pas l'étiquette, dans le db sera stocké la clé. J'utilise l'étiquette uniquement pour la communication avec le client, MyChoiceField ne fait que mapper les valeurs avec les touches et viceversa. Je pense que c'est plus compréhensible pour les clients qui n'ont pas besoin de connaître la représentation interne de ces données. – SimoV8

+0

Je suppose que c'est correct pour votre cas particulier. Je ne suis pas convaincu que le fait de passer une étiquette (au lieu d'une clé) dans 'to_internal_value' est la meilleure pratique à suivre. En général, le passage d'une représentation clé du client aurait plus de sens. À moins que cela ne soit impossible dans votre cas, votre solution est acceptable. +1;) – mariodev

1

Il n'y a pas d'autre solution que de surcharger votre sérialiseur. S'il vous plaît jeter un oeil here, pour voir comment cela peut être fait.

+0

Salut, merci, je l'ai lu. Cela fonctionne pour obtenir des ressources mais pas pour créer/mettre à jour une nouvelle entité, une idée? – SimoV8

+0

Oh, vous ne l'avez pas mentionné ... alors peut-être que vous pouvez définir le [Champ Sérialiseur ChoiceField] (http://www.django-rest-framework.org/api-guide/fields/#choicefield) dans votre sérialiseur à la place. – mariodev

+0

J'ai déjà essayé mais cela ne fonctionne pas:/ – SimoV8