We're required to have two separate forms for two different types of users. Call them Client
and Provider
. Client would be the parent, base user, while Provider is a sort of extension. At any point a Client could become a Provider as well, while still maintaining status and information as a Client. So a Provider has both permissions as a Client and as a Provider.
I'm new to Django. All we're trying to do is register either user type, but have a one to one relation between Provider and Client tables if a user registers as a Provider straight away.
The issue we're having is in the adapter, we think. A provider registers fine, but ends up in the users_user
table with no entry in the generated users_provider
table. Is it the way we're trying to save and relate these two entities in the database, or something else?
We're trying to utilize allauth for authentication and registration.
Our code:
models.py:
class User(AbstractUser):
name = models.CharField(_('Name of User'), blank=True, max_length=255)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username})
SEX = (
("M","MALE"),
("F","FEMALE"),
)
birthdate = models.DateField(_('Birth Date'), default=django.utils.timezone.now, blank=False)
sex = models.CharField(_('Sex'), choices=SEX, max_length=1, default="M")
isProvider = models.BooleanField(_('Provider'), default=False)
#Using User, not models.Model
class Provider(User):
HAS_BUSINESS = (
('YES','YES'),
('NO','NO'),
)
#Resolving asociation 1:1 to User
#NOTE: AUTH_USER_MODEL = users.User in setting
owner = models.OneToOneField(settings.AUTH_USER_MODEL)
has_business = models.CharField(_('Do you have your own business?'),max_length=2, choices=HAS_BUSINESS, default='NO')
isProvider = True
our forms.py
class ProviderForm(SignupForm,ModelForm):
name = forms.CharField(label='Name', strip=True, max_length=50)
lastname = forms.CharField(label='Last Name', strip=True, max_length=50)
Provider.isProvider = True
class Meta:
model = Provider
fields = '__all__'
exclude = GENERAL_EXCLUSIONS + [
'owner',
]
class ClientForm(SignupForm,ModelForm):
name = forms.CharField(label='Name', strip=True, max_length=50)
lastname = forms.CharField(label='Last Name', strip=True, max_length=50)
class Meta:
model = User
fields = "__all__"
exclude = GENERAL_EXCLUSIONS
def is_active(self):
return False
def __init__(self, *args, **kwargs):
super(ClientForm, self).__init__(*args, **kwargs)
views.py:
class ProviderRegisterView(SignupView):
template_name = 'account/form_provider.html'
form_class = ProviderForm
redirect_field_name = 'next'
view_name = 'registerprovider'
success_url = None
def get_context_data(self, **kwargs):
ret = super(ProviderRegisterView, self).get_context_data(**kwargs)
ret.update(self.kwargs)
return ret
registerprovider = ProviderRegisterView.as_view()
#View para el formulario de registro de usuarios clientes
class ClientRegisterView(SignupView):
template_name = 'account/form_client.html'
form_class = ClientForm
redirect_field_name = 'next'
view_name = 'registerclient'
success_url = None
def get_context_data(self, **kwargs):
ret = super(ClienteRegisterView, self).get_context_data(**kwargs)
ret.update(self.kwargs)
return ret
registerclient = ClienteRegisterView.as_view()
finally, our adapter.py:
#Per allauth documentation, settings changed:
#ACCOUNT_ADAPTER = 'projectname.users.adapters.RegisterUserAdapter'
class RegisterUserAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
data = form.cleaned_data
user.first_name = data['name']
user.last_name = data['lastname']
#Saving Client info
user.sex = data['sex']
user.birthdate = data['birthdate']
#Normal allauth saves
user.username = data['username']
user.email = data['email']
if user.isProvider:
p = Provider()
p.owner = user
p.has_business = data['has_business']
if 'password1' in data:
user.set_password(data['password1'])
else:
user.set_unusable_password()
self.populate_username(request, user)
if commit:
#Save user
user.save()
#If it's also a Provider, save the Provider
if user.isProvider:
p.save()
return user
Any help or tips would be greatly appreciated. If I left something out, please let me know. I'm not sure if the problem is in the model itself, the way we represent the form, or the adapter. The way it stands, it doesn't matter what form we use, it's always saved as the base User table (our Client) and the Provider table never gets information saved to it.