我通过使用内置注册和激活功能发送令牌激活电子邮件来注册用户。注册表单是UserCreationForm的子类,用于为电子邮件和 date_of_birth 验证添加额外字段。我的代码如下:
forms.py:
class UserRegisterForm(UserCreationForm):
date_of_birth = forms.DateField(widget=forms.SelectDateWidget(years=range(2017, 1900, -1)))
email = forms.EmailField(required=True)
def clean_username(self):
username = self.cleaned_data.get('username')
if User.objects.filter(username__iexact=username).exists():
raise forms.ValidationError('Username already exists')
return username
def clean_date_of_birth(self):
'''
Only accept users aged 13 and above
'''
userAge = 13
dob = self.cleaned_data.get('date_of_birth')
today = date.today()
if (dob.year + userAge, dob.month, dob.day) > (today.year, today.month, today.day):
raise forms.ValidationError('Users must be aged {} years old or above.'.format(userAge))
return dob
def clean_email(self):
email = self.cleaned_data.get('email')
if User.objects.filter(email__iexact=email).exists():
raise forms.ValidationError('A user has already registered using this email')
return email
def clean_password2(self):
'''
we must ensure that both passwords are identical
'''
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2 and password1 != password2:
raise forms.ValidationError('Passwords must match')
return password2
class Meta:
model = User
fields = ['username', 'email', 'date_of_birth', 'password1', 'password2']
views.py:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
date_of_birth = form.cleaned_data.get('date_of_birth')
new_user = form.save(commit=False)
new_user.is_active = False
new_user.save()
current_site = get_current_site(request)
message = render_to_string('email_activation_link.html', {
'new_user':new_user,
'domain':current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(new_user.pk)),
'token': account_activation_token.make_token(new_user),
})
mail_subject = 'Activate your Frac account.'
to_email = EmailMessage(mail_subject, message, to=[email])
to_email.send()
return render(request, 'register_confirm.html', {'form': form})
else:
form = UserRegisterForm()
return render(request, 'register.html', {'form': form})
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
new_user = User.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, User.DoesNotExist):
new_user = None
if new_user is not None and account_activation_token.check_token(new_user, token):
new_user.is_active = True
new_user.save()
return render(request, 'register_complete.html', {})
else:
return render(request, 'registration_incomplete.html', {})
models.py:
class UserProfile(models.Model):
'''
Extends the Django User model
'''
user = models.OneToOneField(settings.AUTH_USER_MODEL,
related_name='profile')
email = models.EmailField(blank=True)
date_of_birth = models.DateField(blank=True, null=True)
profile_photo = models.ImageField(blank=True)
following = models.ManyToManyField(settings.AUTH_USER_MODEL,
blank=True,
related_name='followed_by')
def __str__(self):
return 'Followers({});Following({})'.format(self.user.followed_by.all().count(),self.get_following().count())
def post_save_user_receiver(sender, instance, created, *args, **kwargs):
'''
Django signals to automatically create
a user profile when a user object is created
'''
if created:
new_profile, is_created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(post_save_user_receiver, sender=settings.AUTH_USER_MODEL)
admin.py:
from django.contrib import admin
from .models import UserProfile
class ProfileAdmin(admin.ModelAdmin):
list_display = ['user', 'id', 'date_of_birth', 'profile_photo', '__str__']
admin.site.register(UserProfile, ProfileAdmin)
新用户已正确注册。但是,只有用户名和电子邮件字段会显示在Django管理网站的“用户”部分中。我无法弄清楚为什么 date_of_birth 字段没有为新注册的用户显示。
答案 0 :(得分:1)
您尚未扩展用户模型,您已添加了相关的用户个人资料。您不会在任何地方执行任何操作来实际创建此用户配置文件的实例,或使用表单中的数据填充它们;您可以在视图中获取DOB和电子邮件值,然后继续忽略它们。
您需要使用这些值创建配置文件:
if form.is_valid():
new_user = form.save(commit=False)
new_user.is_active = False
new_user.save()
email = form.cleaned_data.get('email')
date_of_birth = form.cleaned_data.get('date_of_birth')
UserProfile.objects.create(user=new_user, email=email, date_of_birth=date_of_birth)
答案 1 :(得分:1)
date_of_birth
字段属于UserProfile
模型,因此您不应将其包含在用户表单fields
中。
class UserRegisterForm(UserCreationForm):
...
class Meta:
model = User
fields = ['username', 'email']
在您的视图中,您可以获取信号创建的个人资料,并设置出生日期,您可以从已清理的数据中获取该日期。
if form.is_valid():
email = form.cleaned_data.get('email')
date_of_birth = form.cleaned_data.get('date_of_birth')
new_user = form.save(commit=False)
new_user.is_active = False
new_user.save()
profile = new_user.profile
profile.date_of_birth=date_of_birth
profile.save()