Пользователи могут видеть только свои объекты в 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 процентов моих проблем.
Благодарю всех за помощь в этом вопросе.