Пользователи могут видеть только свои объекты в Django

У меня есть приложение, в котором пользователи могут создавать свои собственные компании. Но в представлении я хочу, чтобы они видели только свои записи в представлении. Я видел похожие вопросы на этой платформе, но они не работают так, как ожидалось. Ниже приведен мой код.

Models.Py

from django.contrib.auth.models import User

class Company (models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    company_name = models.CharField(max_length=100, null=True)
    mailing_address = models.CharField(max_length=100, null=True)
    physical_address =  models.CharField(max_length=100, null=True)

class Meta:
    verbose_name_plural = "Companies"

def __str__(self):
    return self.company_name

views.py

@login_required(login_url='login')
def company (request):
    all_companies = Company.objects.filter(user=request.user)
    count= Company.objects.all().count()
    context = {'all_companies': all_companies, 'count': count}
    return render(request, 'company/company.html', context)

forms.py

class CompanyForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
    super(CompanyForm, self).__init__(*args, **kwargs)

    self.fields['company_name'].widget.attrs = {'class': 'input',}
    self.fields['date_created'].widget.attrs = {'class': 'input',}
    self.fields['mailing_address'].widget.attrs = {'class': 'input',}
    self.fields['physical_address'].widget.attrs = {'class': 'input',}
    
class Meta:
    model = Company
    fields = ('company_name', 'date_created', 'mailing_address', 'physical_address',)

В основном это работает для того, чтобы каждый пользователь видел только ту компанию, которую он создал. Однако, я могу успешно создавать компании со стороны администратора, но появляется очевидная проблема. Мне приходится вручную выбирать пользователей из поля формы = users в форме администратора, как показано на рисунке ниже, чтобы иметь возможность создавать и сохранять компании. Такое же поведение и на фронт-энде с формой. Это выглядит неправильно.

Как сделать так, чтобы компания автоматически указывала на владельца (пользователя), который ее создал, без необходимости вручную заставлять форму выбирать пользователя.

страница администратора

Если вы хотите, чтобы пользователь автоматически добавлялся в админку Django, вы можете переопределить save_model соответствующей ModelAdmin: https://docs.djangoproject.com/en/4.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.save_model

Если вы хотите, чтобы он заполнялся, когда пользователи создают компании с помощью форм, вы можете установить атрибут user следующим образом:

# assuming request.user is available
company_form = form.save(commit=False)
company_form.user = request.user
company_form.save()

Поскольку пользователь является внешним ключом. Вы можете воспользоваться преимуществами

метод 'formfield_for_foreignkey' в классе ModelAdmin.

Этот метод выполняется для внешних полей, объявленных в модели. Здесь мы можем проверить, был ли он выполнен для пользователя или нет, если да, то мы можем предварительно заполнить его значение. Вы можете настроить форму администратора, создав класс ModelAdmin в файле admin.py для модели Company

@admin.register(Company)
class CompanyAdmin(admin.ModelAdmin):
    form = CompanyForm

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'user':
            kwargs['initial'] = request.user.id
            return db_field.formfield(**kwargs)

        return super(CompanyAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

В классе ModelAdmin вы можете указать класс формы для дальнейшей настройки.

Примечание, это будет только предварительное заполнение значения, значение пользователя может быть изменено в форме. Чтобы избежать этого, вы можете сделать поле пользователя нередактируемым и доступным для чтения.

Наконец-то я нашел решение, по крайней мере для пользовательского поля в форме Company.

Здесь приведен четкий способ сделать это: https://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-editing/#models-and-request-user

views.py: Я добавил form.instance для поля user, чтобы убедиться, что он выбирает текущего пользователя и вводит его в форму.

def company_form (request):
form = CompanyForm()
if request.method == 'POST':
    # Request files helps upload other files such as images
    form = CompanyForm(request.POST, request.FILES) 
    #This automatically inserts the user without exposing the form field
    form.instance.user = request.user 
  
    if form.is_valid():
        form.save() 
    return redirect('company')

Затем я изменил поле модели для пользователя так, чтобы оно не было редактируемым.

models.py

class Company (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, editable=False)

Это гарантирует, что никто не сможет редактировать пользователя, включая администратора. В идеале это решает 90 процентов моих проблем.

Благодарю всех за помощь в этом вопросе.

Вернуться на верх