Разрешите только владельцам родительской модели создавать дочернюю модель при использовании общих представлений (django-guardian)

В настоящее время у меня есть две модели, Parent и Child, с отношениями один-ко-многим. Я использую встроенные общие представления на основе классов для CRUD над родительской моделью, где я использую миксин django-guardian для предотвращения выполнения этих операций пользователями, не владеющими объектом Parent, что работает хорошо. Однако я хочу иметь возможность добавлять детей к родительскому объекту. Это прекрасно работает с использованием общего CreateView и modelform, где pk родителя - это kwarg, переданный в url. Однако если пользователь изменит pk в URL на pk родительского объекта другого пользователя, он сможет добавить к нему дочерний объект. Я хочу использовать django-guardian (или другие средства) для предотвращения добавления пользователем дочернего объекта к родительскому объекту другого пользователя. Можно ли это сделать или это нужно делать каким-то другим способом? Я добился этого, проверяя принадлежность объекта Parent текущему пользователю в get_form_kwargs в CreateView, но это кажется халтурой, и я бы предпочел django-guardian.

(Я также не использую ключ 'pk' в производстве, а вместо него использую другой ключ 'uuid', но тем не менее я хотел бы устранить эту брешь в безопасности).

Код:

models.py

class Parent(models.Model): 
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) 
    name = models.CharField(max_length=200, null=True, blank=True)
    
    class Meta:
        permissions = (('manipulate', 'Manipulate'))

class Child(models.Model):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
    name = models.CharField(max_length=200, null=True, blank=True)

views.py

class CreateChildForm(ModelForm):
    class Meta:
        fields = ('name', 'parent')
        model = models.Child

    def __init__(self, *args, **kwargs):
        self.parent = kwargs.pop('parent')
        super().__init__(*args, **kwargs)
        self.fields['parent'].initial = self.parent
        self.fields['parent'].widget = HiddenInput()

class CreateChild(LoginRequiredMixin, CreateView):
    model = models.Child
    form_class = CreateChildForm
    success_url = reverse_lazy('home')

    def get_form_kwargs(self):
        try:
            self.parent = Parent.objects.get(uuid=self.kwargs['uuid'], user=self.request.user)
        except:
            raise PermissionDenied()

        kwargs = super().get_form_kwargs()
        kwargs['parent'] = self.parent
        return kwargs

    def form_valid(self, form):
        form.instance.parent = self.parent
        return super().form_valid(form)
Вернуться на верх