2013-06-24 9 views
33

Ich verwende das django rest framework, um eine API zu erstellen. Ich habe folgende Modelle:Abrufen eines Fremdschlüsselwertes mit django-rest-framework-Serialisern

class Category(models.Model): 
    name = models.CharField(max_length=100) 

    def __unicode__(self): 
     return self.name 


class Item(models.Model): 
    name = models.CharField(max_length=100) 
    category = models.ForeignKey(Category, related_name='items') 

    def __unicode__(self): 
     return self.name 

Um einen Serializer für die Kategorien zu erstellen ich tun würde:

class CategorySerializer(serializers.ModelSerializer): 
    items = serializers.RelatedField(many=True) 

    class Meta: 
     model = Category 

... und das würde mir mit:

[{'items': [u'Item 1', u'Item 2', u'Item 3'], u'id': 1, 'name': u'Cat 1'}, 
{'items': [u'Item 4', u'Item 5', u'Item 6'], u'id': 2, 'name': u'Cat 2'}, 
{'items': [u'Item 7', u'Item 8', u'Item 9'], u'id': 3, 'name': u'Cat 3'}] 

Wie würde ich mich über das Gegenteil von einem Punkt Serializer bekommen, das heißt:

[{u'id': 1, 'name': 'Item 1', 'category_name': u'Cat 1'}, 
{u'id': 2, 'name': 'Item 2', 'category_name': u'Cat 1'}, 
{u'id': 3, 'name': 'Item 3', 'category_name': u'Cat 1'}, 
{u'id': 4, 'name': 'Item 4', 'category_name': u'Cat 2'}, 
{u'id': 5, 'name': 'Item 5', 'category_name': u'Cat 2'}, 
{u'id': 6, 'name': 'Item 6', 'category_name': u'Cat 2'}, 
{u'id': 7, 'name': 'Item 7', 'category_name': u'Cat 3'}, 
{u'id': 8, 'name': 'Item 8', 'category_name': u'Cat 3'}, 
{u'id': 9, 'name': 'Item 9', 'category_name': u'Cat 3'}] 

Ich habe die Dokumente auf reverse relationships für den Rest-Framework gelesen, aber das scheint das gleiche Ergebnis wie die nicht umgekehrten Felder zu sein. Fehle ich etwas Offensichtliches?

Antwort

50

Verwenden Sie einfach ein verwandtes Feld ohne Einstellung many=True.

Beachten Sie, dass auch, weil Sie die Ausgabe category_name, aber das tatsächliche Feld ist category, müssen Sie verwenden, um das source Argument auf dem Serializer Feld mit dem Namen mögen.

Folgendes sollte Sie die Ausgabe, die Sie benötigen ...

class ItemSerializer(serializers.ModelSerializer): 
    category_name = serializers.RelatedField(source='category', read_only=True) 

    class Meta: 
     model = Item 
     fields = ('id', 'name', 'category_name') 
+0

Vielen Dank Tom – hellsgate

+15

was über alle Felder des catagory Modell retriving ?? – Clayton

+4

, wenn Sie alle Felder der Kategorie Modell abrufen möchten die Kategorie Serializer machen und haben es in Code wie category_name = CategorySerliazer() –

13

Eine andere Sache, die Sie tun können, ist:

  • eine Eigenschaft in Ihrem Item Modell erstellen, die den Kategorienamen zurückgibt und
  • setzen Sie es als ReadOnlyField frei.

Ihr Modell würde wie folgt aussehen.

class Item(models.Model): 
    name = models.CharField(max_length=100) 
    category = models.ForeignKey(Category, related_name='items') 

    def __unicode__(self): 
     return self.name 

    @property 
    def category_name(self): 
     return self.category.name 

Ihr Serializer würde so aussehen. Beachten Sie, dass der Serializer automatisch den Wert der Modelleigenschaft category_name erhält, indem das Feld mit demselben Namen benannt wird.

class ItemSerializer(serializers.ModelSerializer): 
    category_name = serializers.ReadOnlyField() 

    class Meta: 
     model = Item 
+1

habe ich nicht mit diesem Zweck verwendet. Aber ich wusste nicht über die Verwendung von "@ Eigenschaft". Also, vielen Dank. Es war wirklich nützlich. Es hilft mir mit anderen Elementen im Serializer. – joseglego

16

In der aktuellen DRF (3.6.3) Version dieses für mich gearbeitet

class ItemSerializer(serializers.ModelSerializer): 
    category_name = serializers.CharField(source='category.name') 

    class Meta: 
     model = Item 
     fields = ('id', 'name', 'category_name') 
+0

Arbeitete wie eine Magie, danke! – UserNotFoundException