Разрешите только владельцам родительской модели создавать дочернюю модель при использовании общих представлений (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)