0

In my pervious question I asked how I can automatically save the user submitting the form. I found the form_valid method to be the best in that case. However in my models I also have a user profile model like this

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)
...

As you can see I used the One to One method to make my UserProfile

As before in my models.py I have my reports model

...
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})
...

My question how I can make it so that the department field will load from the user profile? I would hope to eventually make it possible for users in the same department to be able to view and update each others Reports.

As before:

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})
owescott
  • 7
  • 2
  • Is there a reason why you link `Report` to `User`, rather than to `Profile`? If you already create `Profile` as 1to1 for `User` then, from an application design perspective, it would be the better choice to link to `Profile` rather than to `User` – j-i-l Feb 06 '22 at 11:42
  • ...I'm guessing that makes since now that I think about sorry I've been pulling an all nighter. I guess my concern is the profile data loaded from the user data upon login. Sorry if I'm not wording that right – owescott Feb 06 '22 at 13:00

2 Answers2

0

I advise you to use related_name in your ForeignKeys. Set the department field of both models as following:

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')
    ...

From now on, Department objects that are related to User.Profile you can access like that:

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

And you can use it in making QuerySet for user:

Report.objects.filter(department=self.request.user.profile.department)
# it returns all Report objects, that have exactly the same department as the user

Or using our new relationship:

department = self.request.user.profile.department
reports_for_user = department.reports.all()

But I can see one problem. You are using Company model for ForeignKey in Report. It has to be the same Department model for both Profile and Report models for such easy option to work. Also you definitely should not mix naming in single project. You can set relation with Company as another field:

company = models.ForeignKey(Company, null=True, on_delete=models.SET_NULL)
NixonSparrow
  • 6,130
  • 1
  • 6
  • 18
-1

Here are some steps to help you autofill some fields:

  1. Get the user from self.request.user. How to access current user in Django class based view
  2. Get the profile: get user profile in django
  3. Pass the required fields as context variables: https://www.geeksforgeeks.org/how-to-pass-additional-context-into-a-class-based-view-django/
  4. Pass it into javascript. How can I pass my context variables to a javascript file in Django?
  5. Set the value like this: Set the value of an input field

DONE!