How to make sequential signup pages with Django allauth?
I currently have a single page signup form implemented with allauth
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.EmailField(_('Professional email address'), unique=True)
username = models.CharField(_("User Name"), blank=False, max_length=255, unique=True)
first_name = models.CharField(_("First Name"), null=True, max_length=255, default='')
last_name = models.CharField(_("Last Name"), null=True, max_length=255, default='')
country = CountryField(_("Country of Practice"), blank_label='(Country of Practice)', blank = False, default='GB')
terms = models.BooleanField(verbose_name=_('I have read and agree to the terms and conditions'), default=False)
def get_absolute_url(self):
return reverse(
"users:detail", kwargs={"username": self.username}
)
objects = UserManager()
And this is the forms.py
class UserCreationForm(forms.UserCreationForm):
error_message = forms.UserCreationForm.error_messages.update(
{"duplicate_username": _("This username has already been taken.")}
)
username = CharField(label='User Name',
widget=TextInput(attrs={'placeholder': 'User Name'}))
class Meta(forms.UserCreationForm.Meta):
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2', 'terms']
field_order = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2', 'terms']
def clean_terms(self):
is_filled = self.cleaned_data['terms']
if not is_filled:
raise forms.ValidationError('This field is required')
return is_filled
def clean_username(self):
username = self.cleaned_data["username"]
if self.instance.username == username:
return username
try:
User._default_manager.get(username=username)
except User.DoesNotExist:
return username
raise ValidationError(
self.error_messages["duplicate_username"]
)
I would like however for the first sign up page to have a ‘next’ button at the bottom and then there would be a second page where the user input separate details (the data input here might vary based on the inputs in the first page). The Django ‘form tools’ form wizard seems well suite to this but I can’t work out how to integrate it with all auth
Any suggestions much appreciated
as a first step have a look on the templates in the github repo:
https://github.com/pennersr/django-allauth/tree/master/allauth/templates/
account/
base.html
...
login.html
....
openid/
...
you can check the original pages and modify/overwrite them by creating folders/files in your app templates folder:
your_app/
templates/
your_app/ # this is the app templates standard folder
account/ # this one is to overwrite allauth->account templates
base.html
login.html
...
openid/
...
Then you can change the action taken when buttons are clicked and that way could hook in an intermediate view/page. Remains to clarify how eventually posted parameters are kept in the chain of pages.
You can use Django's FormWizard
to implement a multi-page form for user sign up, and integrate it with Django AllAuth by subclassing FormWizard
and customizing its behavior as necessary.
Here's a basic example to get you started:
from formtools.wizard.views import SessionWizardView
from allauth.account.forms import SignupForm
class UserSignupWizard(SessionWizardView):
form_list = [SignupForm, UserCreationForm]
def done(self, form_list, **kwargs):
# Implement logic to save the form data to the database
# ...
return HttpResponseRedirect(reverse("success_url"))
In the example above, form_list
is a list of forms that will be used in the wizard. In this case, you are using both the SignupForm
provided by Django AllAuth
and your custom UserCreationForm
. The done method is called when all the forms in the wizard have been filled out and submitted. This is where you can implement logic to save the form data to the database, send email confirmations, etc.
Note that you may need to customize the forms or the UserSignupWizard
class to fit your specific needs.