Предотвращает ли getjqueryset () в админке Django сохранение вредоносных объектов? - PullRequest
0 голосов
/ 12 ноября 2018

Я разрабатываю мультитенантное приложение в Django.В администраторе Django некоторые наборы запросов фильтруются на основе пользователя с использованием get_queryset().

До настоящего времени, когда пользователь обновлял объект из формы изменения Django, я проверял данные, создавая ModelAdmin, используя фабричную функцию для захвата объекта HttpRequest, затем убедитесь, что user объекта Guest был текущим пользователем:

ПРИМЕР

models.py

class Guest(models.Model):
    guest_name = models.CharField(max_length=64)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

admin.py

@admin.register(Guest)
class GuestAdmin(admin.ModelAdmin):
    def get_queryset(self, request)
        qs = super().get_queryset(request)
        return qs.filter(user=request.user)

    def get_form(self, request, obj=None, **kwargs):
        self.form = _guest_admin_form_factory(request)
        return super().get_form(request, obj, **kwargs)

forms.py

def _guest_admin_form_factory(request):
    class GuestAdminForm(forms.ModelForm):
        class Meta:
            model = Guest
            exclude = []

         def clean_user(self):
             user = self.cleaned_data.get('user', None)
             if not user:
                 return user
             if user != request.user:
                 raise forms.ValidationError('Invalid request.')
             return user
    return GuestAdminForm

Мне пришло в голову, что Django может использовать метод get_queryset(), чтобы проверить это для меня, так как некоторые простые журналы показали, что метод вызывается дважды, когда объект обновляется из формы изменений.

Это так, или мне нужно придерживаться проверки с помощью ModelAdmin формы?

1 Ответ

0 голосов
/ 13 ноября 2018

Документированный способ сделать это - определить has_change_permission():

@admin.register(Guest)
class GuestAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        return super().get_queryset(request).filter(user=request.user)

    def has_change_permission(self, request, obj=None):
        return (obj is None or obj.user == request.user)

Нет необходимости разбираться с формой.

...