2015-09-28 10 views
6

Ich habe es mit Django Rest Framework-Projekt zu tun und die generische Antwort für meine Ansicht ist nicht das, was der App-Client erwartet.Django Rest Framework - Zuordnung von Serializer-Feldern zu einem Datenbankspaltennamen

Der App-Client erwartet, dass das Feld der verwandten Modelle in der Datenbank angezeigt wird. Beispiel gegeben: Modell Stadt hat einen Fremdschlüssel für das Ländermodell, dargestellt durch eine Spalte country_id.

Gibt es eine Option, um die Standardfelder der Serializer in eine benutzerdefinierte zu "mappen"? Ich habe die Django Rest Framework-Dokumentation überprüft, aber ich habe nur "serializer_field_mapping" gefunden, aber ich weiß nicht, ob es meinen Anforderungen entspricht und ich weiß auch nicht, wie ich es verwenden soll.

Irgendwie habe ich eine enge Annäherung davon, aber nur im Fall für das Abrufen von Daten - creating/update warf einige Fehler, die ich nicht bekommen habe, wie man verwaltet. :(

Darf ich meine models.py Datei anhängen, plus die tatsächliche Ausgabe und die gewünschte Ausgabe. Außerdem, wenn es möglich ist, möchte ich Daten abrufen, die mit Land/Region zusammen mit der Datenbankspalte verknüpft sind field_id Namen.

Vielen Dank im Voraus,

models.py

from django.db import models 
from django.contrib.postgres.fields import ArrayField 


class Country(models.Model): 

    name = models.CharField(max_length=150, unique=True, blank=False) 

    class Meta: 
     db_table = 'countries' 


class Region(models.Model): 

    name = models.CharField(max_length=150, unique=True, blank=False) 
    code = models.CharField(max_length=150, blank=True) 

    class Meta: 
     db_table = 'regions' 


class City(models.Model): 

    country = models.ForeignKey(Country) 
    region = models.ForeignKey(Region, null=True, blank=True, default=None) 
    name = models.CharField(max_length=150, unique=True, blank=False) 
    postal_codes = ArrayField(models.CharField(max_length=12, blank=True), null=True, blank=True, default=None) 

    def __str__(self): 
     if not self.region: 
      return '%s (%s)' % (self.name, self.country.name) 
     return '%s, %s (%s)' % (self.name, self.region.name, self.country.name) 

    class Meta: 
     db_table = 'cities' 

Actual Ou tput:

[ 
    { 
    "id": 1, 
    "name": "San Francisco", 
    "postal_codes": null, 
    "country": 1, 
    "region": 1 
    }, 
    { 
    "id": 2, 
    "name": "Palo Alto", 
    "postal_codes": null, 
    "country": 1, 
    "region": 1 
    }, 
    { 
    "id": 3, 
    "name": "New York City", 
    "postal_codes": null, 
    "country": 1, 
    "region": 2 
    }, 
    { 
    "id": 4, 
    "name": "London", 
    "postal_codes": null, 
    "country": 2, 
    "region": null 
    } 
] 

gewünschte Ausgabe:

[ 
    { 
    "id": 1, 
    "country_id": 1, 
    "region_id": 1, 
    "name": "San Francisco", 
    "postal_codes": null 
    }, 
    { 
    "id": 2, 
    "country_id": 1, 
    "region_id": 1, 
    "name": "Palo Alto", 
    "postal_codes": null 
    }, 
    { 
    "id": 3, 
    "country_id": 1, 
    "region_id": 2, 
    "name": "New York City", 
    "postal_codes": null 
    }, 
    { 
    "id": 4, 
    "country_id": 2, 
    "region_id": null, 
    "name": "London", 
    "postal_codes": null 
    } 
] 

Antwort

2

Danke an alle. Endlich hab ich es. Siehe nachstehenden Code. Ich beantworte meine Frage, da es keine Option gibt, eine große Anzahl von Zeilen zu einem Antwortkommentar hinzuzufügen.

serializers.py

from rest_framework import serializers 
from .models import Country, Region, City 


class CountrySerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Country 
     fields = ('id', 'name') 


class RegionSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Region 
     fields = ('id', 'name', 'code') 


class CitySerializer(serializers.ModelSerializer): 

    country_id = serializers.PrimaryKeyRelatedField(
     queryset=Country.objects.all(), 
     required=True, 
     source='country', 
    ) 
    region_id = serializers.PrimaryKeyRelatedField(
     queryset=Region.objects.all(), 
     allow_null=True, 
     required=False, 
     source='region', 
    ) 

    country = CountrySerializer(
     read_only=False, 
     required=False, 
    ) 
    region = RegionSerializer(
     required=False, 
     allow_null=True, 
     read_only=True, 
    ) 

    class Meta: 
     model = City 
     fields = (
      'id', 
      'country', 'region', 
      'name', 'postal_codes', 
      'country_id', 'region_id', 
     ) 
5

Sie können das source Parameter eines Feldes auf dem Serializer dies zu erreichen. Zum Beispiel:

from rest_framework import serializers 

from .models import City 


class CitySerializer(serializers.ModelSerializer): 
    country_id = serializers.IntegerField(source='country') 
    region_id = serializers.IntegerField(source='region') 

    class Meta: 
     model = City 
     fields = ('id', 'country_id', 'region_id', 'name', 'postal_codes') 

EDIT: Als Jaroslaw wies darauf hin, wenn es auf diese Weise tun, Sie brauchen nicht die source umfassen. Beachten Sie jedoch, dass es einfach nicht reicht, country_id oder region_id in die fields Liste aufzunehmen. Sie müssen das Feld auf dem Serialisierungsprogramm weiterhin angeben, z. B. , und es auch in fields einschließen.

+0

Es ist nicht OP scheint braucht 'source', da er ids in' country_id' und 'region_id' haben will. –

+0

Sicher, aber es wird nicht einige Django Rest Framework Standardvalidierung bieten. 'POST/cities/{Name: San José, country_id: 999999}' liefert einen HTML-Code mit 'IntegrityError at/cities/Einfügen oder Aktualisieren in Tabelle" cities "verletzt Fremdschlüssel-Constraint" cities_country_id_2cc874aa51973821_fk_countries_id "DETAIL: Schlüssel (country_id) = (999) ist in der Tabelle "countries" nicht vorhanden. "Das gleiche gilt für Einschränkungen der Datenbanktabelle. – jordimarinvalle

+0

@ JordiMarínValle Verwenden Sie ['PrimaryKeyRelatedField'] (http: //www.django-rest-framework.org/api-guide/relations/# primarykeyrelatedfield) anstelle von 'IntegerField'. –

Verwandte Themen