2016-05-16 3 views
0

Ich habe ein Modell Ticket mit einem Auswahlfeld status genannt:Wie der zugehörigen Wert eines Auswahlfeld schicken

STATUS_CHOICES = (
    ('1', 'Open'), 
    ('2', 'Resolved'), 
    ('3', 'Won\'t fix') 
) 
status = models.CharField(
    "Status", 
    max_length=1, 
    choices=STATUS_CHOICES, 
    blank=False, 
    default='1' 
) 

ich für die API Django Rest Rahmen verwenden. Der Standardmodell-Serialisierer sendet den ersten Wert der Wahl, d. H. 1 anstelle von Open. Wie kann ich den zweiten Text als Antwort senden?

Hier ist ein Teil meines Serializer:

class TicketSerializer(serializers.ModelSerializer): 
    status = serializers.ChoiceField(choices=Ticket.STATUS_CHOICES)   

    class Meta: 
     model = Ticket 
     fields = ('status',) 

Antwort

1

Der folgende Ansatz löst dieses Problem. Wir können ein benutzerdefiniertes Feld für Choices erstellen.

class ChoicesField(serializers.Field): 
    def __init__(self, choices, **kwargs): 
     self._choices = choices 
     super(ChoicesField, self).__init__(**kwargs) 

    def to_representation(self, obj): 
     return self._choices[int(obj) - 1] # obj is the first value 

    def to_internal_value(self, data): 
     return getattr(self._choices, data) 

Dies ist ähnlich der von Tahir vorgeschlagenen Lösung, aber auf eine sauberere Art und Weise.

4

API im Allgemeinen Daten zu holen verwendet werden, nicht UI-Darstellung der Daten. In ('1', 'Choice 1'), '1' ist der Wert überall zu speichern und zu verwenden, 'Choice 1' ist seine UI-Repräsentation, die wir explizit verwenden müssen, wenn wir sie brauchen (in der UI, also Templates).

DjangoAdmin ist eine vollständige Django-App, daher wird die UI-Darstellung explizit verwendet. Wenn Sie Django Forms verwenden, müssen Sie diese auch explizit verwenden. Es wird nicht automatisch verwendet.

In Vorlage, wenn Sie {{ my_form_choice_field.value }} tun, wird es '1' nicht 'Choice 1' verwenden. Sie müssen {{ my_form_choice_field.get_my_form_choice_field_display }}explizit (in der UI-Ebene) verwenden, um 'Choice 1' zu erhalten.

Also, wie ich mit APIs begann, werden in der Regel verwendet, um Daten zu holen, nicht es ist UI-Darstellung. Deshalb verwendet DjangoRestFramework auch nur den ursprünglichen Wert und nicht seine UI-Repräsentation (JUST LIKE DJANGO).

Nun zur Beantwortung Ihrer Frage, wenn Sie wirklich die UI-Darstellung zurückgeben wollen. Dann müssen Sie die to_representation-Methode von BaseSerializer überschreiben, um den Wert durch seine UI-Repräsentation zu ersetzen und to_internal_value zu überschreiben, um die UI-Repräsentation beim Speichern wieder auf den Wert zu setzen.

Sie können ein Beispiel (aus der Dokumentation) here sehen.

Zitieren der Dokument Beispielcode hier oben verlinkt.

class HighScoreSerializer(serializers.BaseSerializer): 
    def to_internal_value(self, data): 
     score = data.get('score') 
     player_name = data.get('player_name') 

     # Perform the data validation. 
     if not score: 
      raise ValidationError({ 
       'score': 'This field is required.' 
      }) 
     if not player_name: 
      raise ValidationError({ 
       'player_name': 'This field is required.' 
      }) 
     if len(player_name) > 10: 
      raise ValidationError({ 
       'player_name': 'May not be more than 10 characters.' 
      }) 

     # Return the validated values. This will be available as 
     # the `.validated_data` property. 
     return { 
      'score': int(score), 
      'player_name': player_name 
     } 

    def to_representation(self, obj): 
     return { 
      'score': obj.score, 
      'player_name': obj.player_name 
     } 

    def create(self, validated_data): 
     return HighScore.objects.create(**validated_data) 
Verwandte Themen