Использование профиля пользователя для автоматической загрузки информации в поля формы
В своем предыдущем вопросе я спросил, как я могу автоматически сохранить пользователя, отправляющего форму. Я нашел метод form_valid наилучшим в этом случае. Однако в моих моделях у меня также есть модель профиля пользователя, подобная этой
models.py
....
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
title = models.CharField(max_length=24)
first_name = models.CharField(max_length=35)
last_name = models.CharField(max_length=35)
email = models.EmailField(max_length=64)
phone_number = models.CharField(max_length=12)
department = models.ForeignKey(Department,null=True,on_delete=models.SET_NULL)
supervisor = models.ForeignKey('self',blank=True,null=True,on_delete=models.SET_NULL)
...
Как вы видите, я использовал метод One to One для создания своего UserProfile
Как и раньше в моем models.py у меня есть модель отчетов
...
class Report(models.Model):
id = models.UUIDField(primary_key=True,default=uuid.uuid1,editable=False)
department = models.ForeignKey(Company,null=True,on_delete=models.SET_NULL)
user= models.ForeignKey(User,on_delete=models.PROTECT)
submission_date= models.DateField(auto_now=True) #invisible to user
submission_time = models.TimeField(auto_now=True) #invisible to ,user
date = models.DateField(default=now,blank=False)
time = models.TimeField(default=now,blank=False,help_text="hh:mm:ss")
location = PlainLocationField()
building = models.ForeignKey(bld,null=True,on_delete=models.SET_NULL)
size = models.PositiveIntegerField()
notes = models.TextField(blank=True)
def __str__(self):
return f'{self.date} {self.time} ({self.department})
...
Мой вопрос, как я могу сделать так, чтобы поле отдела загружалось из профиля пользователя? Я надеюсь в конечном итоге сделать так, чтобы пользователи одного отдела могли просматривать и обновлять отчеты друг друга.
Как и раньше:
form.py
class ReportForm(forms.ModelForm):
class Meta:
model = Report
fields = '__all__'
location = PlainLocationField()
def redirect():
return redirect("Report")
views.py
class ReportCreate(LoginRequiredMixin,CreateView):
Template = "templates\reports\Report.html"
model = Report
fields = '__all__'
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.save()
return super(ReportCreate, self).form_valid(form)
def get_success_url(self):
return reverse('Report')
def get_absolute_url(self):
return reverse('Report', kwargs={'pk':self.pk})
Вот несколько шагов, которые помогут вам автозаполнить некоторые поля:
- Получение пользователя из self.request.user. Как получить доступ к текущему пользователю в представлении на основе класса в Django
- Получение профиля: get user profile in django
- Передайте необходимые поля как контекстные переменные: https://www.geeksforgeeks.org/how-to-pass-additional-context-into-a-class-based-view-django/ .
- Передайте это в javascript. Как я могу передать мои контекстные переменные в файл javascript в Django? .
- Установите значение следующим образом: Установите значение поля ввода .
СДЕЛАНО!
Советую вам использовать related_name в вашей ForeignKeys. Установите поле department обеих моделей следующим образом:
class Profile(models.Model):
...
department = models.ForeignKey(Department, null=True, on_delete=models.SET_NULL, related_name='profiles')
...
class Report(models.Model):
...
department = models.ForeignKey(Department, null=True, on_delete=models.SET_NULL, related_name='reports')
...
Отныне к объектам Department, связанным с User.Profile, можно обращаться так:
Department.profiles.all() # it returns QuerySet of all related to Department Profile objects
Department.reports.all() # it returns QuerySet of all related to Department Report objects
И вы можете использовать его при создании QuerySet для пользователя:
Report.objects.filter(department=self.request.user.profile.department)
# it returns all Report objects, that have exactly the same department as the user
Или используя наши новые отношения:
department = self.request.user.profile.department
reports_for_user = department.reports.all()
Но я вижу одну проблему. Вы используете модель Company для ForeignKey в отчете. Это должна быть одна и та же модель Department для обеих моделей Profile и Report, чтобы такой простой вариант работал. Также вам определенно не следует смешивать именование в одном проекте. Вы можете установить связь с Company в качестве другого поля:
company = models.ForeignKey(Company, null=True, on_delete=models.SET_NULL)