Search code examples
methodsdjango-viewsdjango-formscelerydjango-celery

How to pass data between views and forms using form_valid


I have a simple UserRegistration view:

class UserRegistration(generic.CreateView):
    form_class = RegisterForm
    template_name = 'registration/registration.html'
    success_url = reverse_lazy('home')

    def form_valid(self, form):
        user = form.save()
        login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
        return redirect(self.success_url)

Which logs the User in after they register. I wanted to send an email confirmation letting the User know they successfully signed up. So I added a method to my RegisterForm:

class RegisterForm(UserCreationForm):
    email = forms.EmailField()
    first_name = forms.CharField(max_length=100)
    last_name = forms.CharField(max_length=100)

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')

    def registration_email(request):
        send_mail(
            'Welcome aboard!',
            'Thanks for signing up...',
            NOTIFICATION_EMAIL,
            ['example@email.com'],
            fail_silently=True
        )

Then I call it in my view with form.registration_email().

Now, this works but it's hardcoded. I want the recipient email to be the new User's email they just entered. That info should be available in the view, but how do I pass that to my form? I just can't figure out how to pass data from my views to my form methods, so that I can then call those methods in my view if form is valid.

Should I be doing it like this? Or should I be doing all this in form_valid instead? I also plan on using Celery in the future, so is there a preferred way with regards to that as well?


Solution

  • Where should to be send_email method depends on your logic in project.

    In your case:

    class RegisterForm(UserCreationForm):
    
        ...
    
        def registration_email(self, request):
            # it should be only after from.is_valid()
            # to protect us:
            if self.is_valid():
                send_mail(
                    'Welcome aboard!',
                    'Thanks for signing up...',
                    NOTIFICATION_EMAIL,
                    [self.cleaned_data['email']],
                    fail_silently=True
                )