2017-07-23 1 views
1

Je veux que mes visiteurs aient une fonction pour créer et obtenir la liste des propositions.Les objets imbriqués Django Rest Framework créent avec request.user

L'utilisateur envoie toutes les données à l'exception de l'auteur de la proposition (parce que le auth est l'utilisateur lui-même), donc je suis en train d'étendre request.data avec request.user comme ceci:

# proposals/views.py 
class ProposalsList(ListCreateAPIView): 
    permission_classes = (IsAuthenticatedOrReadOnly,) 
    queryset = Proposal.objects.all() 
    serializer_class = ProposalSerializer 

    def post(self, request, *args, **kwargs): 
     serializer = self.get_serializer(data={ 
      **request.data, 
      "author": request.user.id, 
      }) 
      serializer.is_valid(raise_exception=True) 
      self.perform_create(serializer) 
      headers = self.get_success_headers(serializer.data) 
      return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) 

Bien que, Je veux obtenir la liste des propositions avec l'auteur sérialisé (utilisateur), donc mon sérialiseur ressemble à:

# proposals/serializers.py 
class ProposalSerializer(serializers.ModelSerializer): 
    author = UserSerializer() 
    class Meta: 
     model = SeekerProposal 
     fields = ('text', 'author') 

le problème est que je reçois liste des utilisateurs correctement (sérialisés à dict), mais je ne peux pas POST (créer une nouvelle) Proposition, car elle veut t o "auteur" est un dict (il arrive parce que j'utilise un serializer imbriqué = UserSerializer()).

Questions:

  1. Est-il possible de laisser vue être ListCreateAPIView et auteur = UserSerializer() tout en obtenir la liste des données sérialisés et créer proposition de request.user.id?
  2. Peut-être existe-t-il un autre moyen d'ajouter un utilisateur autorisé au champ auteur de la proposition?

De plus, ceci est mon modèle:

# proposals/models.py 
class Proposal(models.Model): 
    text = models.TextField(blank=False, null=False) 
    author = models.ForeignKey(
     settings.AUTH_USER_MODEL, 
     on_delete=models.SET(get_sentinel_user), 
    ) 

Réponse

utilisateur @zaidfazil m'a aidé avec une solution. je devais ajouter juste une champ supplémentaire à mon sérialiseur pour les détails de l'auteur à afficher sérialisés:

# proposals/serializers.py 
class ProposalSerializer(serializers.ModelSerializer): 
    author_details = UserSerializer(source='author', read_only=True) 
    class Meta: 
     model = SeekerProposal 
     # author will be user id, and author_details will be serialized dict 
     fields = ('text', 'author', 'author_details') 

Parce que author est encore juste ID utilisateur et author_details est read_only=True j'obtenir toutes les données sur à GET demande et peut créer une nouvelle proposition par author=request.user.id.

Un moment:

Je n'ai pas utilisé blank=True sur author terrain, parce que je dois être sûr que ce champ ne soit pas vide. Donc, ma vue est la même que je l'ai écrit ci-dessus (post sur ProposalsList).

Encore une fois, merci beaucoup à @zaidfazil! Si j'ai écrit quelque chose de mal s'il vous plaît écrivez-moi, je suis un peu nooby sur stackoverflow.

+0

Une sorte de réponse a été la création d'une nouvelle sérialiseur appelée ProposalNestedSerializer qui hérite mon ProposalSerializer et étend author = UserSerializer(), tout en le retirant de ProposalSerializer. Alors maintenant, j'utilise ProposalNestedSerializer pour GET (et obtenir l'auteur sérialisé en réponse) et en utilisant ProposalSerializer avec POST (et peut créer des propositions avec juste request.user.id) – Dionid

Répondre

0

manière habituelle serait de définir votre champ author comme blank=True dans vos modèles et en passant l'utilisateur lors de l'enregistrement du sérialiseur,

author = models.ForeignKey(settings.AUTH_USER_MODEL, 
    on_delete=models.SET(get_sentinel_user), blank=True) 

serializers.py,

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('email', 'first_name', .....) 

class ProposalSerializer(serializers.ModelSerializer): 
    author_details = UserSerializer(source='author', read_only=True) 
    class Meta: 
     model = SeekerProposal 
     fields = ('text', 'author', 'author_details') 

Alors, selon vous,

class ProposalsList(ListCreateAPIView): 
    permission_classes = (IsAuthenticatedOrReadOnly,) 
    queryset = SeekerProposal.objects.all() 
    serializer_class = SeekerProposalSerializer 

    def perform_create(self, serializer): 
     serializer.save(author=self.request.user) 
+0

Merci! Mais theres encore des problèmes: Tout d'abord, sur GET j'ai besoin d'une liste de propositions avec auteur sérialisé et sur POST création de proposition avec author = request.user.id (mais je ne peux pas, car si j'utilise author = UserSerializer() dans ProposalSerializer demande l'objet lors de la création) Deuxièmement, je ne veux pas que l'auteur soit vide = Vrai, car c'est un peu dangereux (j'ai besoin d'authentification pour beaucoup de situations) – Dionid

+0

rendant l'auteur 'blank = True' ne causerait aucun effet , cuz assignant l'utilisateur ne sera manipulé que dans les coulisses. Sinon, il perdrait la sécurité elle-même, aussi le champ 'user' est toujours obligatoire. Pour votre question sur les détails de l'auteur, vous pouvez ajouter des champs 'read_only' dans la requête GET, pour afficher les détails des informations sur l'auteur existant. Je mettrai à jour ma réponse sous peu. – zaidfazil

+0

Vous m'avez donné le moyen de résoudre ce problème! Je vais le décrire dans ma question. Mais deux choses: je dois être sûr que l'auteur n'est pas vide, donc je ne veux vraiment pas user 'blank = True' et je ne l'ai pas fait, aussi pouvez-vous ajouter 'author_details' pour tuple dans votre réponse pour quelqu'un d'autre ne pas être confus pourquoi ils reçoivent une erreur) – Dionid