Empty UpdateView form for extended AbstractUser

I’m trying to build my first custom user model extending AbstractUser as MyUser which then has a OneToOne relationship with my Employee class (and, later, with other classes such as Contractor). I’m using GCBV, and creating and displaying a new employee work as expected but the update form contains the correct fields but they are empty and I don’t understand why.
The database contains the expected data from the create.
I have other GCBVs working with full CRUD for classes without the user connection so I hoped that I understood enough to get the user part working - clearly not! Do I need to do something extra for Update that isn’t needed for Create or for non-user-related models?

Any help would be much appreciated - this is my first post here so I hope that I have provided enough detail:


class MyUser( AbstractUser ):
	# Uses username, first_name, last_name and email from AbstractUser
	is_employee = models.BooleanField( default = False, verbose_name=_('Staff'))
	is_contractor = models.BooleanField( default = False, verbose_name=_('Contractor'))

class Employee( models.Model ):
	user = models.OneToOneField(
		settings.AUTH_USER_MODEL,		# MyUser

	is_staff_admin = models.BooleanField( default=False, null=True, verbose_name=_('Administrator') )


class EmployeeUpdateView( UpdateView ):
	model = Employee
	pk_url_kwarg = 'employee_pk'
	template_name = 'employees/employee_create_and_update.html'
	form_class = EmployeeChangeForm 
	success_url = None
	context_object_name = 'employee'


class MyUserChangeForm( UserChangeForm ):
	class Meta:
		model = get_user_model()   # MyUser
		fields = (
			# AbstractUser fields
			# MyUser fields
			# None yet - is_employee is not visible on the form

class EmployeeChangeForm( MyUserChangeForm ):
	class Meta( MyUserChangeForm.Meta ):
		model = MyUser


{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block content %}
	<form method='POST'>
		{% csrf_token %}
		{{ form|crispy }}
		{% include "create_update_buttons_snippet.html" %}
{% endblock %}


    path( 'employee/update/<int:employee_pk>/',  EmployeeUpdateView.as_view(),        name='employee_update' ),

You’ve got a mismatch between your view and your form:

specifies that the view is to update an instance of the Employee model.

Identifies this form as being for the MyUser model - which isn’t an Employee model.

Thanks Ken - you are right, that must be wrong. I don’t see how I can define a form that includes both the Employee attributes (just the is_staff_admin in my simplified snipped) and the AbstractUser/MyUser attributes (first_name, last_name et al). Do I have to have a view that handles two forms or is there a simpler solution as the Employee and MyUser models are 1:1 related?
The “extend AbstractUser and use 1:1 for the profile” seems to be recommended in many places BUT the examples I have found only describe implementing the Create. Any pointer would be very welcome. Thanks.

The generic CBVs defined within Django are designed to work with a single model. Likewise, a ModelForm is designed to work with a single instance of one model.

That doesn’t mean that other things can’t be done - only that those tools may not be the best way to do them.

See Create a new user, manually - #5 by typonaut as part of another discussion on this topic.

With just one field in play here, I’d use the Model Form for the model with the majority of fields being used, and add the field from the other model to that form. (You’ll have to initialize it when the form is initially rendered, and update it manually when the form is submitted.)

If you had a larger number of fields, I’d create two Django forms and render them within one HTML form. (They’re kept logically separate using the prefix attribute of the form.)

Thanks for your prompt reply. I will try the Model-Form-for-the-model-with-the-most-fields approach and report back.