I'm on my second Django project. On my first project I used all generic views, with only the most basic forms tied directly to a custom user model using UpdateView
.
In this project I'm trying to implement user profile functionality. My custom user model has some extra dummy fields just so I can manipulate the data. This I refer so as the CustomUser
model. I also have a UserAddress
model containing addresses since a user can have more than one address. I have tried looking for other questions, and I get similar questions, but there is always something missing:
Django class based views - UpdateView with two model forms - one submit
Using Multiple ModelForms with Class-Based Views
Multiple Models in a single django ModelForm?
Django: multiple models in one template using forms
I've spent the last day or two looking for the "Django way" of doing what I want to do and have had no luck. My initial thought was that I could use a single template, fed with two ModelForms wrapped in a single <form>
tag. The view would then process each form and update the CustomUser
model and create or update the UserAddress
models. I have figured out how to mash together the functionality using the base View
CBV, but I suspect I'm duplicating a lot of functionality that I could probably find already done in Django. This is my view, where I handle the form instantiating manually, and feed the context
.
class UserDetailsView(View):
def get(self, request):
user = request.user
user_basic = CustomUser.objects.get(pk=user.pk)
basic_form = UserBasicForm(instance=user_basic)
user_address = UserAddress.objects.get(user=user.pk)
billing_address_form = UserAddressForm(instance = user_address)
context = {'basic_form':basic_form,'billing_address_form':billing_address_form}
return render(request, 'mainapp/profile.html', context)
My post
is the same at this point, as I haven't done the actual validation and saving yet.
class UserBasicForm(forms.ModelForm):
class Meta(forms.ModelForm):
model = CustomUser
fields = (
'username',
'first_name',
'last_name',
)
labels = {
'username':'Username',
'first_name':'First Name',
'last_name':'Last Name',
}
class UserAddressForm(forms.ModelForm):
class Meta(forms.ModelForm):
model = UserAddress
fields = (
'description',
'addressee',
'company',
'address_1',
'address_2',
'city',
'prov_state',
'post_zip',
'country',
)
labels = {
'description':'Address Description',
'addressee':'Addressee',
'company':'Company Name',
'address_1':'Address',
'address_2':'Address 2',
'city':'City',
'prov_state':'Province or State',
'post_zip':'Postal or Zip Code',
'country':'Country',
}
class CustomUser(AbstractUser):
objects = CustomUserManager()
def __str__(self):
return self.email
class UserAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)
description = models.CharField(max_length = 256, default='Description')
addressee = models.CharField(max_length = 256,)
company = models.CharField(max_length = 256, default='Self')
address_1 = models.CharField(max_length = 256,)
address_2 = models.CharField(max_length = 256,)
city = models.CharField(max_length = 256,)
prov_state = models.CharField(max_length = 256,)
post_zip = models.CharField(max_length = 256,)
country = models.CharField(max_length = 256,)
def __str__(self):
return self.description
Please go easy on me, I'll take most advice offered.
Edit After reviewing some other SO questions and Django form examples, it appears that the final answer probably isn't SO material. That said, my observation is that for the Django built-in CBVs, the "best" base view is that which you can minimize or simplify the code you add. Using a TemplateView or FormView for my project in this case just depends on which methods I choose to re-write or override and for that, I'm still open to suggestions.