2013-07-26 2 views
1

Disons que j'ai ce modèle simple:Modèle sérialiseur: choisir les champs à afficher et ajouter des champs personnalisés

class BlogPost(models.Model): 
    author = models.ForeignKey(MyUser) 
    body = models.TextField() 
    title = models.CharField(max_length=64) 
    urlid = models.CharField(max_length=32) 
    private_data = models.CharField(max_length=64) 

private_data contient des données que je ne veux pas exposer à l'API (!). J'utilise un ModelSerializer:

class BlogPostSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = BlogPost 

    def __init__(self, *args, **kwargs): 
     # Don't pass the 'request' arg up to the superclass 
     request = kwargs.pop('request', None) 
     # Instatiate the superclass normally 
     super(ModelSerializer, self).__init__(*args, **kwargs) 
     self.request = request 

    def absolute_url(self, blogpost): 
     return blogpost.get_absolute_url(self.request) 

La méthode absolute_url a besoin du request pour déterminer le nom de domaine (dev ou prod par exemple) et si elle a été faite en http ou https.

Je veux spécifier quels champs dans le modèle vont être retournés par le sérialiseur (ne pas exposer private_data par exemple). Assez simple:

class BlogPostSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = BlogPost 
     fields = ('author', 'body', 'title', 'urlid',) 

    # The same jazz after that 

Très bien, cela fonctionne. Maintenant, je veux aussi revenir absoluteURL:

class BlogPostSerializer(serializers.ModelSerializer): 
    absoluteUrl = serializers.SerializerMethodField('absolute_url') 

    class Meta: 
     model = BlogPost 
     fields = ('author', 'body', 'title', 'urlid',) 

    # The same jazz after that 

Eh bien, sans surprise, cela renvoie uniquement les champs I spécifiés, sans absoluteURL. Comment puis-je retourner seulement certains champs du modèle ET absoluteUrl, calculés à partir du sérialiseur?

Si je ne spécifie pas fields j'obtiens le absoluteUrl, mais avec tous les champs du modèle (y compris private_data). Si j'ajoute 'absoluteUrl' à fields, j'obtiens une erreur parce que blogpost.absoluteUrl n'existe pas (pas de surprise ici). Je ne pense pas que je pourrais utiliser cette méthode http://django-rest-framework.org/api-guide/serializers.html#specifying-fields-explicitly parce que je dois le request pour obtenir le absoluteURL (ou puis-je spécifier des arguments à la méthode du modèle?)

+0

Évidemment, je pourrais déplacer la logique de 'blogpost.get_absolute_url' vers le sérialiseur mais je préfère laisser la logique dans le modèle. De plus, je ne suis pas un grand fan des fonctions de collage de copie. –

Répondre

4

If I don't specify fields I do get the absoluteUrl, but with all the model's fields (including private_data). If I add 'absoluteUrl' to fields I get an error because blogpost.absoluteUrl doesn't exist (no surprises there).

Vous devriez juste ajouterez 'absoluteUrl' au tuple fields, et ça devrait marcher, alors quelle erreur voyez-vous?

The absolute_url method needs the request to determine the domain name (dev or prod for example) and if it was made in http or https.

Notez que vous pouvez également passer à travers le contexte du sérialiseur sans modfiying le __init__, il suffit de passer un context={'request': request} lors de l'instanciation sérialiseur. L'ensemble par défaut des vues génériques le fait pour vous, vous pouvez donc accéder à self.context['request'] dans l'une des méthodes de sérialisation. (Notez que c'est ainsi que les liens hypertextes peuvent renvoyer des URLs entièrement qualifiées)

+0

L'erreur que je vois est la suivante: 'Fichier" /usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py ", ligne 206, dans get_fields new [clé] = ret [clé] KeyError: 'url'' J'utilise 'url' comme nom au lieu de' absolute_url' et ça semble gâcher les choses ... Quand j'utilise réellement' absolute_url' ça fonctionne très bien. Eh bien, merci d'avoir pris le temps de répondre! Et merci pour le contexte, je serai sûr de l'utiliser. –

Questions connexes