Django ограничивает выбор внешнего ключа поля user на основе пользователя, который вошел в систему

У меня есть модель под названием Client с полем user в качестве внешнего ключа:

class Client(models.Model):
    name = models.CharField(_('Client Name'), max_length=100)
    address = models.CharField(_('Client Address'), max_length=100, blank=True)
    demand = models.PositiveIntegerField(_('Client Demand'))
    location = models.PointField(_('Client Location'))
    created_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )

    class Meta:
        default_permissions = ('add', 'change', 'delete', 'view')

    def __str__(self):
        return self.name

Я хочу ограничить выбор поля пользователя в форме администратора на основании того, кто вошел в систему

django admin form

Например, здесь я вошел в систему под именем agung, поэтому я хочу, чтобы поле выбора пользователя ограничивалось только agung, но здесь я могу получить доступ к другим именам пользователей, таким как admin и rizky.

Я попробовал это

class ClientAdminForm(forms.ModelForm):
    class Meta:
        model = Client
        fields = "__all__"


    def __init__(self, request, *args, **kwargs):
        super(ClientAdminForm, self).__init__(request, *args, **kwargs)
        if self.instance:
            self.fields['user'].queryset = request.user

но кажется, что он не может принять запрос в качестве аргумента (я полагаю, потому что это не Http запрос)

Вы можете сделать это, переопределив атрибут base_fields экземпляра вашей формы следующим образом :

views.py

# Before instantiate the form class
 ClientAdminForm.base_fields['user'] = forms.ModelChoiceField(queryset=self.request.user)

# Now you can instantiate the form
form = ClientAdminForm(...)

NB : Делайте переопределение base_fields непосредственно перед инстанцированием формы

Вы можете переписать метод get_form вашей Admin Model, чтобы добавить текущий request.user в качестве свойства класса. Далее вы можете прочитать его в конструкторе формы и отфильтровать запрос.


class ClientAdmin(admin.ModelAdmin):
    # [...]
    
    def get_form(self, request, obj=None, **kwargs):
        form_class = super(ClientAdmin, self).get_form(request, obj, **kwargs)
        form_class.set_user(request.user)

        return form_class


class ClientAdminForm(forms.ModelForm):
    # [...]

    @classmethod
    def set_user(cls, user):
        cls.__user = user

    def __init__(self, *args, **kwargs):
        super(ClientAdminForm, self).__init__(request, *args, **kwargs)
        if self.instance:
            self.fields['user'].queryset = \
                self.fields['user'].queryset.filter(pk=self.__user.pk)

Однако, проще всего исключить это поле из формы и обновлять его в методе save_model:


class ClientAdminForm(forms.ModelForm):
    # [...]
    
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        obj.save()
Вернуться на верх