2017-08-23 3 views
1

J'ai une classe model avec ModelChooserBlock dans StreamField et si j'ouvre mon Django Rest Framework, je n'ai pas de résultat satisfaisant. Spécifiquement "Ingrédient" devrait avoir un lien vers les ingrédients ou directement la base de données.Django Rest Framework n'affiche pas le contenu de StreamField

HTTP 200 OK 
Allow: GET, HEAD, OPTIONS 
Content-Type: application/json 
Vary: Accept 

{ 
    "id": 1, 
    "meta": { 
     "type": "cultinadb.Menu", 
     "detail_url": "http://127.0.0.1:8000/api/v2/menu/1/" 
    }, 
    "title": "", 
    "Ingredient": [ 
     { 
      "type": "zutaten", 
      "value": 2, 
      "id": "647d762f-ec26-4c78-928a-446344b1cb8a" 
     }, 
     { 
      "type": "zutaten", 
      "value": 1, 
      "id": "6ab4e425-5e75-4ec0-ba63-8e7899af95e2" 
     } 
    ], 
} 

Voici mon modèle:

from django.db import models 
from wagtail.api import APIField 
from wagtailmodelchooser import register_model_chooser 
from wagtailmodelchooser.blocks import ModelChooserBlock 

@register_model_chooser 
class Ingredient(models.Model): 
    name = models.CharField(max_length=255) 
    picture_url = models.URLField(blank=True) 
    translate_url = models.URLField(blank=True) 

    def __str__(self): 
     return self.name 

@register_model_chooser 
class Menu(models.Model): 
    Ingredient = StreamField([ 
     ('zutaten', ModelChooserBlock('kitchen.Ingredient')) ], 
     null=True, verbose_name='', blank=True) 

    panels = [ 
     MultiFieldPanel(
      [ StreamFieldPanel('Ingredient') ], 
      heading="Zutaten", classname="col5" 
     ), 
    ] 

    def __str__(self): 
     return self.title 

    api_fields = [ 
     APIField('Ingredient'), 
    ] 

I tried to add it as shown here avec sérialiseur, mais j'obtenu des erreurs. J'ai créé serializer.py et a ajouté ce code

class MenuRenditionField(Field): 
    def get_attribute(self, instance): 
     return instance 
    def to_representation(self, menu): 
     return OrderedDict([ 
      ('title', menu.Ingredient.name), 
      ('imageurl', menu.Ingredient.picture_url), 
      ('imageurl', menu.Ingredient.translate_url), 
     ]) 

Puis j'ai changé mes api_fields comme celui-ci

api_fields = [ 
    APIField('Ingredient', serializer=MenuRenditionField()), 
] 

L'erreur que je reçois lorsque vous ajoutez ce code.

AttributeError at /api/v2/menu/1/ 
'StreamValue' object has no attribute 'name' 
    Request Method: GET 
    Request URL: http://127.0.0.1:8000/api/v2/menu/1/ 
    Django Version: 1.11.1 
    Exception Type: AttributeError 
    Exception Value: 
    'StreamValue' object has no attribute 'name' 

Je serai très reconnaissant pour l'aide. Merci!

Répondre

3

Vous pouvez personnaliser la sortie API d'un bloc StreamField en remplaçant la méthode get_api_representation. Dans ce cas, il pourrait ressembler à:

class IngredientChooserBlock(ModelChooserBlock): 
    def get_api_representation(self, value, context=None): 
     if value: 
      return { 
       'id': value.id, 
       'name': value.name, 
       # any other relevant fields of your model... 
      } 

Utilisez ensuite IngredientChooserBlock('kitchen.Ingredient') en place de ModelChooserBlock('kitchen.Ingredient') dans votre définition de Streamfield.

+0

Cela fonctionne !! Merci beaucoup! @gasman https://i.stack.imgur.com/dvXVO.png – khashashin

+0

Hey @gasman Merci pour votre aide, en fait vous l'avez fait pour moi deux fois. ce code fonctionne bien, mais il ne peut pas représenter ensemble de données Streamfield pour examle j'ai 'ingrédient = Streamfield ([ ('zutaten', IngredientChooserBlock ('kitchen.Ingredient'))], null = True, verbose_name = « », blanc = True) ' et imprime une erreur dans DRF comme celui-ci \t ' objet de type « StreamValue » est pas JSON serializable' – khashashin

+0

@khashashin de cette erreur, il semble que vous êtes de retour un objet complexe quelque part dans la réponse 'get_api_representation', comme retourner' value' au lieu de 'value.name' etc. - DRF ne peut fonctionner qu'avec des types simples de Python tels que des chaînes, des listes et des dicts. Je devrais voir le code complet pour étudier plus loin, cependant - je suggérerais l'ouverture comme nouvelle question. – gasman