2 votes

Héritage des autorisations entre les modèles apparentés dans le DRF

J'ai 3 modèles comme ci-dessous :

class CustomUser(AbstractUser):
    pass

class PropertyPost(models.Model):
    owner = models.ForeignKey(
        get_user_model(),
        related_name='posts4thisowner',
        on_delete=models.CASCADE)

class Image(models.Model):
    prop_post = models.ForeignKey(
        PropertyPost,
        related_name='images4thisproperty',
        on_delete=models.CASCADE)

L'idée ici est que l'utilisateur peut afficher plusieurs PropertyPost et que chaque PropertyPost peut contenir plusieurs images.

Les choses fonctionnent bien. Mon problème se situe au niveau des autorisations. J'ai défini un ensemble de permissions comme suit pour mes vues PropertyPostDetail, et aucune permission pour la vue ImageDetail :

class PropertyPostDetail(generics.RetrieveUpdateDestroyAPIView):
 ...
    permission_classes = (
        permissions.IsAuthenticatedOrReadOnly,
        custompermission.IsCurrentUserOwnerOrReadOnly,
        )

class ImageList(generics.ListCreateAPIView):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    name = 'image-list'

class ImageDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    name = 'image-detail'

ce qui signifie que seul le propriétaire de l'article peut modifier ses articles.

Étant donné que le modèle d'image concerne le PropertyPost, je m'attendais à ce que cette autorisation s'applique également aux images. Cependant, il semble que n'importe quel utilisateur puisse modifier n'importe quelle image, ce qui est évidemment un défaut. Ma question est la suivante : comment puis-je configurer ma vue image pour qu'elle hérite des permissions de son parent, le PropertyPost ?

1voto

Nabat Farsi Points 451

Ok, j'espère qu'il y aura une solution plus simple, mais voici comment j'ai résolu le problème. J'ai essayé de ne pas créer de propriétaire pour le modèle image, parce que le modèle image a PropertyPost comme parent, qui a un propriétaire. L'image devrait donc hériter de ce propriétaire :

class Image(models.Model):

    prop_post = models.ForeignKey(
        PropertyPost,
        related_name='images4thisproperty',
        on_delete=models.CASCADE)
    prop_post_owner=models.CharField(max_length=150,null=True,blank=True)

et ceci serait le sérialiseur :

class ImageSerializer(serializers.HyperlinkedModelSerializer):
    prop_post = serializers.SlugRelatedField(queryset=PropertyPost.objects.all(),
                                             slug_field='pk')
    prop_post_owner = serializers.ReadOnlyField(source='prop_post.owner.username')
    class Meta:
        model = Image
        fields = (
            'pk',
            'url',
            'prop_post',
            'prop_post_owner'
       )

De cette façon, mon modèle d'image a un propriétaire qui vient du PropertyPost.

Maintenant, au niveau de la liste, l'utilisateur peut créer un objet et comme il n'est pas clair quel objet l'utilisateur va sélectionner, les permissions personnalisées échoueront. Enfin, voici comment j'empêche les non-propriétaires de créer un champ d'image pour une propriété :

class ImageList(generics.ListCreateAPIView):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer
    name = 'image-list'
    ....
    def perform_create(self, serializer):
        obj=PropertyPost.objects.get(pk=int(self.request.data['prop_post']))
        if self.request.user!=obj.owner:
            raise ValidationError('you are not the owner')
        serializer.save(prop_post_owner=self.request.user)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X