0

I have created a model Agent that is in a OneToOne relation with the User model. I managed to create a form where I can edit the Agent(user) details, but I would like to populate the form with the existing details of the model(Agent/user). Found something similar here but it is not using Class based views.

models.py ->

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    is_organisor = models.BooleanField(default=True)
    is_agent = models.BooleanField(default=False)

class Agent(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)   
    organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
    def __str__(self):
        return self.user.email

forms.py ->

from django import forms
from django.contrib.auth import get_user_model

User = get_user_model() 

class AgentModelForm(forms.ModelForm):
    class Meta:
        model = User
        fields = (
            'email',
            'username',
            'first_name',
            'last_name'
        )

views.py ->

class AgentUpdateView(OrganisorAndLoginRequiredMixin,generic.UpdateView):
    template_name = "agents/agent_update.html"
    form_class = AgentModelForm
    queryset = Agent.objects.all()
    def get_success_url(self):
        return reverse("agents:agent_list")
Kertz
  • 9
  • 6
  • Are you saying you want to update both the Agent object and the User object in the same view? If so, it can be done, but I find a functional view as in your linked question is a lot cleaner. Have a look at this question https://stackoverflow.com/questions/15497693/django-can-class-based-views-accept-two-forms-at-a-time for further details – SamSparx Nov 23 '22 at 09:49
  • The update part is working, the form is working, .it modifies the data of the Agent model, all I want is that the form is populated with the data specific to the model. – Kertz Nov 23 '22 at 10:06
  • See my answer. Use the User model as a base for the Agent model. And use Agent like a normal model, with all the User fields built into it. Any changes you make to the Agent object will be made to the User object as well. It's like a hidden OneToOne link – LaCharcaSoftware Nov 23 '22 at 10:16

2 Answers2

0

I don't see any advantage in using a OneToOne field. In your case it's better to use a base class (with the User model):

models.py:

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    is_organisor = models.BooleanField(default=True)
    is_agent = models.BooleanField(default=False)

class Agent(User): 
    organisation = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
    def __str__(self):
        return self.email

So, now, 'email', 'username', 'first_name' and 'last_name' are fields of your Agent model.

forms.py

from django import forms
from .models import Agent

class AgentModelForm(forms.ModelForm):
    class Meta:
        model = Agent
        fields = (
            'email',
            'username',
            'first_name',
            'last_name'
        )

views.py

class AgentUpdateView(OrganisorAndLoginRequiredMixin,generic.UpdateView):
    template_name = "agents/agent_update.html"
    form_class = AgentModelForm
    queryset = Agent.objects.all()
    def get_success_url(self):
        return reverse("agents:agent_list")

This is call Multi-table inheritance. Each model (User and Agent) corresponds to its own database table and can be queried and created individually. The inheritance relationship introduces links between the child model (Agent) and its parent (User) (via an automatically-created OneToOneField).

More information: https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

LaCharcaSoftware
  • 1,075
  • 1
  • 5
  • 13
  • The user model inherits from AbstractUser. I have added some properties to the User model. I've edited the post so you can see the User model – Kertz Nov 23 '22 at 10:25
  • This is not a problem. You can use `class Agent(User)` anyway. I am updating my answer. – LaCharcaSoftware Nov 23 '22 at 10:30
  • pfff... i tried what you said. The thing is that some other errors appear. I'm still a novice Django user so...some things still do not make sense to me. I've used this tutorial to create the app https://www.youtube.com/watch?v=fOukA4Qh9QA. I has a git repo. – Kertz Nov 25 '22 at 07:18
0

There is some confusion in your setup.

The AgentModelForm updates the User model

class AgentModelForm(forms.ModelForm):
    class Meta:
        model = User

So when your Update view calls its queryset Agent.objects.all() it can't find the appropriate model in it. So it can't prepopulate the fields.

Despite the view name, if you update the queryset to User.objects.all you might have better luck.

That said, LaCharcaSoftware's answer is probably a less confusing approach that will serve you better going forward.

SamSparx
  • 4,629
  • 1
  • 4
  • 16