Files
www/membership/members/forms.py
T
claudeandClaude Opus 5.5 98e09627ed Membership: newsletter opt-in at signup and on the profile
An unticked checkbox on registration subscribes the verified address to
the listmonk list (preconfirmed) once the account exists. The profile
page gets a subscribe/unsubscribe toggle, and verified email changes
follow through to listmonk. Newsletter outages never block accounts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 20:27:40 -05:00

38 lines
1.7 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django import forms
from django.conf import settings
from django.contrib.auth.password_validation import validate_password
NEWSLETTER_LABEL = "Email me when new works premiere (about twice a month). Unsubscribe any time."
class RegistrationForm(forms.Form):
uid = forms.RegexField(regex=r"^[a-z][a-z0-9._-]{2,47}$", max_length=48, label="Username", help_text="3–48 lowercase letters, numbers, dots, underscores or hyphens. Start with a letter.")
email = forms.EmailField(max_length=254)
# Explicit opt-in: unticked by default, and only offered when configured.
newsletter = forms.BooleanField(required=False, label=NEWSLETTER_LABEL)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not settings.LISTMONK_ENABLED:
del self.fields["newsletter"]
def clean_email(self):
return self.cleaned_data["email"].strip().casefold()
class PasswordForm(forms.Form):
password = forms.CharField(max_length=1024, widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), label="Password", help_text="Use at least 12 characters. Choose a strong, unique password for your eom.dev account.")
confirm_password = forms.CharField(max_length=1024, widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}), label="Confirm password")
def clean_password(self):
password = self.cleaned_data["password"]
validate_password(password)
return password
def clean(self):
data = super().clean()
if data.get("password") != data.get("confirm_password"):
self.add_error("confirm_password", "Passwords must match.")
return data