3

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.

4

1 に答える 1