Browse Source

Add user module

wavesign
NinjaKelly 2 months ago
parent
commit
703c67a6c7
11 changed files with 350 additions and 0 deletions
  1. +0
    -0
      users/__init__.py
  2. +5
    -0
      users/admin.py
  3. +10
    -0
      users/apps.py
  4. +85
    -0
      users/forms.py
  5. +146
    -0
      users/migrations/0001_initial.py
  6. +0
    -0
      users/migrations/__init__.py
  7. +25
    -0
      users/models.py
  8. +10
    -0
      users/signals.py
  9. +3
    -0
      users/tests.py
  10. +8
    -0
      users/urls.py
  11. +58
    -0
      users/views.py

+ 0
- 0
users/__init__.py View File


+ 5
- 0
users/admin.py View File

@ -0,0 +1,5 @@
from django.contrib import admin
# Register your models here.
from .models import CustomUser
admin.site.register(CustomUser)

+ 10
- 0
users/apps.py View File

@ -0,0 +1,10 @@
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "users"
# 登陆状态信号
def ready(self):
import users.signals

+ 85
- 0
users/forms.py View File

@ -0,0 +1,85 @@
from django import forms
from .models import CustomUser
from django.contrib.auth.hashers import make_password
import re
from django.core.exceptions import ValidationError
class LoginForm(forms.Form):
username = forms.CharField(
label="用户名",
max_length=150,
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': '请输入用户名',
})
)
password = forms.CharField(
label="密码",
widget=forms.PasswordInput(attrs={
'class': 'form-control',
'placeholder': '请输入密码',
})
)
class RegistrationForm(forms.ModelForm):
password_confirm = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(attrs={
'class': 'form-control',
'placeholder': '请再次输入密码'
})
)
email = forms.EmailField(
label="邮箱",
widget=forms.EmailInput(attrs={
'class': 'form-control',
'placeholder': '请输入邮箱'
})
)
agreed_terms = forms.BooleanField(
required=True,
label="我已阅读并同意服务条款",
error_messages={"required": "必须同意服务条款"},
widget=forms.CheckboxInput(attrs={
'class': 'form-check-input'
})
)
class Meta:
model = CustomUser
fields = ['username', 'email', 'password']
widgets = {
'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '请输入用户名'}),
'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': '请输入邮箱'}),
'password': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入密码'}),
}
def clean_password(self):
password = self.cleaned_data['password']
pattern = r'^[A-Za-z\d]{8,}$' # 至少8位,只包含英文字母和数字
if not re.match(pattern, password):
raise ValidationError("密码必须为至少8位的字母和数字组合")
return password
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password and password_confirm and password != password_confirm:
raise forms.ValidationError("两次输入的密码不一致")
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
user.password = make_password(password=self.cleaned_data['password'])
if commit:
user.save()
return user
def clean_email(self):
email = self.cleaned_data['email']
if CustomUser.objects.filter(email=email).exists():
raise forms.ValidationError("该邮箱已被注册")
return email

+ 146
- 0
users/migrations/0001_initial.py View File

@ -0,0 +1,146 @@
# Generated by Django 5.2 on 2025-05-30 01:17
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
]
operations = [
migrations.CreateModel(
name="CustomUser",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"email",
models.EmailField(
blank=True, max_length=254, verbose_name="email address"
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
(
"avatar",
models.ImageField(
blank=True,
default="avatars/default_avatar.png",
null=True,
upload_to="avatars/",
verbose_name="头像",
),
),
(
"agreed_terms",
models.BooleanField(default=False, verbose_name="同意条款"),
),
("activation_token", models.CharField(blank=True, max_length=40)),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
],
options={
"verbose_name": "用户",
"verbose_name_plural": "用户管理",
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
]

+ 0
- 0
users/migrations/__init__.py View File


+ 25
- 0
users/models.py View File

@ -0,0 +1,25 @@
from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
# 基础字段(已继承 username、email、password 等)
avatar = models.ImageField(
upload_to='avatars/',
verbose_name="头像",
blank=True,
null=True,
default='avatars/default_avatar.png' # ✅ 指定默认图片路径
)
agreed_terms = models.BooleanField(default=False, verbose_name="同意条款")
activation_token = models.CharField(max_length=40, blank=True) # 激活令牌字段
class Meta:
verbose_name = "用户"
verbose_name_plural = "用户管理"
def __str__(self):
return self.username
# Create your models here.

+ 10
- 0
users/signals.py View File

@ -0,0 +1,10 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import CustomUser
from MyPage.models import UserProfile
# 注册时同时创建userprofile
@receiver(post_save, sender=CustomUser)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)

+ 3
- 0
users/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 8
- 0
users/urls.py View File

@ -0,0 +1,8 @@
from django.urls import path
from . import views
urlpatterns = [
path('login/', views.login_view, name='login'),
path('register/', views.register_view, name='register'),
path('logout/', views.logout_view, name='logout'),
]

+ 58
- 0
users/views.py View File

@ -0,0 +1,58 @@
import uuid
from django.views.generic.edit import CreateView
from .forms import RegistrationForm, LoginForm
from .models import CustomUser
from django.urls import reverse_lazy
from django.contrib import messages # 可选:添加注册成功提示
from django.shortcuts import render,redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth import logout
def logout_view(request):
logout(request)
return redirect('home')
def register_view(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = form.save()
user.activation_token = uuid.uuid4().hex
user.save()
messages.success(request, "注册成功!请登录")
return redirect('login')
else:
form = RegistrationForm()
return render(request, 'register.html', {'form': form})
def login_view(request):
if request.user.is_authenticated:
return redirect('home')
form = LoginForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
username = form.cleaned_data['username'].strip()
password = form.cleaned_data['password'].strip()
# 检查用户名是否存在
if not CustomUser.objects.filter(username=username).exists():
messages.error(request, "该用户名未注册")
else:
user = authenticate(request, username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('home')
else:
messages.error(request, "账户已被禁用,请联系管理员")
else:
messages.error(request, "密码错误,请重新输入")
else:
messages.error(request, "请输入完整的用户名和密码")
return render(request, 'Login.html', {'form': form})

Loading…
Cancel
Save