• django安装到运行,简单的注册登录


    准备

    工具

    1. vscode 版本: 1.71.2
    2. python(conda) 版本: 3.9.12
    3. mysqlclient 版本: 2.1.1
    4. Django 版本: 4.1
    5. PyMySQL 版本: 1.0.2

    创建

    创建项目

    • 确保环境安装正确

    1. cmd进入需要建立Django项目的文件夹,或在建立Django项目的文件夹内进入cmd
    2. 输入命令
    django-admin startproject projectname  # projectname为项目名称
    
    • 1

    在这里插入图片描述

    • 这种情况是因为使用的是conda环境,此时只需要激活对应的环境就可以了。在这里插入图片描述
      在这里插入图片描述
    1. cd到djangoTest项目文件夹内,输入命令
    django-admin startapp appname   # appname为app的名称
    
    • 1

    在这里插入图片描述

    • 注意一定要进入的项目里面去建立app
    1. 使用vscode打开,对应的目录
      在这里插入图片描述

    2. 创建templates文件夹
      在这里插入图片描述

    3. 注册app,在wutengspro文件夹中的setting.py中
      在这里插入图片描述

    4. 修改时区,语言,配置模板路径

    # 语言修改为中文
    LANGUAGE_CODE = 'zh-hans' 
    # 修改时区
    TIME_ZONE = 'Asia/Shanghai'
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    在这里插入图片描述

    1. 如果使用mysql的话,进行如下配置
    • 确保已经创建了对应的数据库,不然运行时会出错 确保数据库密码正确
    DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql', # sql数据库对应的引擎
                'NAME': 'wuteng', # 数据库名称
                'USER': 'root', # sql数据库登录用户名
                'PASSWORD': '******', # 对应的密码
                'HOST': '127.0.0.1', # sql数据库的ip地址
                'PORT': '3306', # sql数据库端口号
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    在项目文件中的 init.py中添加代码:

    import pymysql
    
    pymysql.install_as_MySQLdb()
    
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    1. 设置静态文件目录 文件上传目录
    #静态文件目录和名称
    STATIC_URL = '/static/'
    #静态文件夹目录的路径
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )
    #文件上传路径,图片上传、文件上传都会存放在此目录
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    运行

    1. 运行命令
    python manage.py runserver
    
    • 1

    在这里插入图片描述

    • 浏览器打开 http://127.0.0.1:8000/
      在这里插入图片描述
    • 至此就创建了一个django项目,运行命令后出现红色字体,不要慌,这是因为没有迁移数据库,只需要再次执行 python manage.py migrate,等待完成,就会在数据库发现Django已经自动创建好了几张表格
      在这里插入图片描述
    • 跟多内容可以看一下官方文档https://docs.djangoproject.com/zh-hans/4.1/releases/

    创建模型

    了解django自带的User模型
    字段

    在这里插入图片描述

    • id:自动生成
    • password:一个密码的哈希值和元数据
    • last_login:用户最后一次登录的日期时间
    • is_superuser:指定该用户拥有所有权限,而不用一个个开启权限
    • username:用户名
    • first_name:名
    • last_name:姓
    • email:电子邮件地址
    • is_staff:指定该用户是否可以访问管理站点
    • is_active:指定该用户账户是否应该被视为活跃账户
    • date_joined:指定账户创建时间的日期时间
    我们可以扩展一下
    1. 加入其他字段,比如:
    • mobile:手机号
    • mobile_confirmed:手机号验证状态:0 未验证 1 已验证
    • avatar:头像地址
    • email_confirmed:邮箱验证状态:0 未验证 1 已验证
    • gender:用户性别:0 未知 1 男性 2 女性
    • status:用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝
    • wx_openid:微信登录的openid
    创建模型,在app下的models中操作
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    import uuid
    import os
    # Create your models here.
    
    # 用于判断文件需要存储的位置
    def user_directory_path(instance, filename):
        ext = filename.split('.')[-1]
        filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
        sub_folder = 'file'
        if ext.lower() in ["jpg", "png", "gif",'jpeg']:
            sub_folder = "avatar"
        if ext.lower() in ["pdf", "docx"]:
            sub_folder = "document"
        return os.path.join(str(instance.user.id), sub_folder, filename)
    
    # 创建自己的用户模型
    class Users(AbstractUser):
        mobile = models.CharField(max_length=11, null=True,
                                  blank=True, verbose_name="手机号码", help_text='用户手机号')
        mobile_confirmed = models.CharField(max_length=1, choices=(("0", "未验证"), ("1", "已验证"),), blank=True,
                                            db_index=True, verbose_name="用户手机号验证状态", help_text='用户手机号验证状态:0 未验证 1 已验证')
        avatar = models.ImageField(upload_to=user_directory_path, blank=True, null=True, verbose_name="用户头像", help_text='用户头像')
        email_confirmed = models.CharField(max_length=1, choices=(("0", "未验证"), ("1", "已验证"),), blank=True,
                                            db_index=True, verbose_name="邮箱验证状态", help_text='邮箱验证状态:0 未验证 1 已验证')
        gender = models.CharField(max_length=1, choices=(("0", "未知"), ("1", "男"),("2", "女"),), blank=True,
                                            db_index=True, verbose_name="性别", help_text='性别')
        status = models.CharField(max_length=1, choices=(("0", "正常"), ("1", "禁用"),("2", "审核中"),("3", "审核拒绝"),), blank=True,
                                            db_index=True, verbose_name="用户状态", help_text='用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝', default='2')
        wx_openid = models.CharField(max_length=128,null=True,blank=True,verbose_name='微信id', help_text='微信id',unique=True)
        
        
        class Meta:
            verbose_name = 'Users'
            get_latest_by = "last_login"
            unique_together = (("mobile", "wx_openid"),)
            
        def __str__(self):
            return f"用户名:{self.username} 手机号:{self.mobile} 邮箱:{self.email} 帐号状态:{self.status}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    这里我们采用了,重写User模型,我们继承了AbstractUser,不需要重写AbstractUser已经定义好的字段了,只需要增加我们需要添加的字段即可,
    在setting.py里添加

    # 指定本项目用户模型类
    AUTH_USER_MODEL = 'users.Users'  # 应用名称.模型类名称
    
    • 1
    • 2

    在这里插入图片描述

    执行命令
    # 生成数据库
    python manage.py makemigrations
    
    • 1
    • 2

    在这里插入图片描述

    # 迁移数据库
    python manage.py migrate
    
    • 1
    • 2

    在这里插入图片描述
    此时数据库可以看到:
    在这里插入图片描述

    配置路由

    在这里插入图片描述
    app中新建urls.py文件,输入:

    from django.urls import re_path, path
    from . import views
    
    app_name = 'users'
    
    urlpatterns = [
        path('login', views.login, name='login'),
        path('regeister', views.regeister, name='regeister'),
        re_path(r'^user/profile/$', views.profile, name='profile'),
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    编写视图函数

    在app的views.py中

    from django.shortcuts import render, get_object_or_404
    from .models import Users
    from django.contrib import auth
    from .form import RegistrationForm, LoginForm, ProfileForm, PwdChangeForm
    from django.http import HttpResponseRedirect
    from django.urls import reverse
    from django.contrib.auth.decorators import login_required
    
    #  注册
    
    
    def register(request):
        if request.method == 'POST':
    
            form = RegistrationForm(request.POST)
            if form.is_valid():
                username = form.cleaned_data['username']
                email = form.cleaned_data['email']
                mobile = form.cleaned_data['mobile']
                password = form.cleaned_data['password2']
    
                # 使用内置User自带create_user方法创建用户,不需要使用save()
                user = Users.objects.create_user(
                    username=username, password=password, email=email, mobile=mobile)
    
                return HttpResponseRedirect("/users/login")
    
        else:
            form = RegistrationForm()
    
        return render(request, 'users/registration.html', {'form': form})
    
    #  登录
    
    
    def login(request):
        if request.method == 'POST':
            form = LoginForm(request.POST)
            if form.is_valid():
                username = form.cleaned_data['username']
                password = form.cleaned_data['password']
    
                user = auth.authenticate(request,username=username, password=password)
                if user is not None and user.is_active:
                    auth.login(request, user)
                    return HttpResponseRedirect(reverse('users:profile'))
    
                else:
                    # 登陆失败
                    return render(request, 'users/login.html', {'form': form,
                                  'message': '账号或密码错误!'})
        else:
            form = LoginForm()
    
        return render(request, 'users/login.html', {'form': form})
    
    # @login_required
    def profile(request):
        
        return render(request, 'users/profile.html')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    在app中新建 utils.py,用于重写 authenticate()方法,实现多种方式登录
    在这里插入图片描述
    在setting.py添加

    AUTHENTICATION_BACKENDS = [
        'users.utils.UsernameMobileAuthBackend',
    ]
    
    • 1
    • 2
    • 3

    编写表单校验

    在app新建forms.py

    from django import forms
    from .models import Users
    import re
    
    # 校验手机号
    
    
    def mobile_check(mobile):
        pattern = re.compile("^((13)|(14)|(15)|(16)|(17)|(18)|(19))\\d{9}$")
        return re.match(pattern, mobile)
    
     # 校验邮箱
    
    
    def email_check(email):
        pattern = re.compile(r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?")
        return re.match(pattern, email)
    
    #  校验密码强度
    
    def paw_check(password):
        pattern1 = re.compile("/^(\d{6,10})|([a-z]{6,10})|([A-Z]{6,10})$/")
        pattern2 = re.compile("/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,20}$/")
        pattern3 = re.compile("/(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{6,10}/")
        
        if re.match(pattern1,password):
            return 1
        if re.match(pattern2,password):
            return 2
        if re.match(pattern3,password):
            return 3
    
    class RegistrationForm(forms.Form):
    
        username = forms.CharField(
            label='用户名',
            required=True,
            min_length=3,
            max_length=8,
            error_messages={
                'required': '用户名不能为空',
                'max_length': '用户名长度不得超过8个字符',
                'min_length': '用户名长度不得少于3个字符',
            })
        email = forms.EmailField(
            label='邮箱',
            required=True,
            error_messages={
                'required': '邮箱不能为空',
            })
        mobile = forms.CharField(
            label='手机号',        
            required=True,
            error_messages={
                'required': '手机号不能为空',
            })
        password1 = forms.CharField(
            label='密码', 
            widget=forms.PasswordInput,
            required=True,
            min_length=6,
            max_length=20,
            error_messages={
                'required': '密码不能为空',
                'max_length': '用密码长度不得超过20个字符',
                'min_length': '密码长度不得少于6个字符',
            })
        password2 = forms.CharField(
            label='确认密码', 
            widget=forms.PasswordInput,
            required=True,
            min_length=6,
            max_length=20,
            error_messages={
                'required': '密码不能为空',
                'max_length': '用密码长度不得超过20个字符',
                'min_length': '密码长度不得少于6个字符',
            })
    
        # Use clean methods to define custom validation rules
    
        def clean_username(self):
            username = self.cleaned_data.get('username')
            filter_result = Users.objects.filter(username__exact=username)
            if filter_result.exists():
                raise forms.ValidationError("用户名已存在!")
    
            return username
    
        def clean_email(self):
            email = self.cleaned_data.get('email')
    
            if email_check(email):
                filter_result = Users.objects.filter(email__exact=email)
                if filter_result.exists():
                    raise forms.ValidationError("邮箱已存在已被绑定!")
            else:
                raise forms.ValidationError("邮箱码格式错误!")
    
            return email
    
        def clean_mobile(self):
            mobile = self.cleaned_data.get('mobile')
    
            if mobile_check(mobile):
                filter_result = Users.objects.filter(mobile__exact=mobile)
                if filter_result.exists():
                    raise forms.ValidationError("手机号已被绑定!")
            else:
                raise forms.ValidationError("手机号码格式错误!")
    
            return mobile
    
        def clean_password1(self):
            password1 = self.cleaned_data.get('password1')
            if paw_check(password1) == 1:
                print("密码强度低")
            if paw_check(password1) == 2:
                print("密码强度中")
            if paw_check(password1) == 3:
                print("密码强度高")        
            return password1
    
        def clean_password2(self):
            password1 = self.cleaned_data.get('password1')
            password2 = self.cleaned_data.get('password2')
    
            if password1 and password2 and password1 != password2:
                raise forms.ValidationError(
                    "密码不一致!")
    
            return password2
    
    
    class LoginForm(forms.Form):
    
        username = forms.CharField(label='用户名', max_length=50)
        password = forms.CharField(label='密码', widget=forms.PasswordInput)
    
        # Use clean methods to define custom validation rules
    
        def clean_username(self):
            username = self.cleaned_data.get('username')
    
            if email_check(username):
                filter_result = Users.objects.filter(email__exact=username)
                if not filter_result:
                    raise forms.ValidationError("邮箱不存在!或未绑定邮箱!")
                
            elif mobile_check(username):
                filter_result = Users.objects.filter(mobile__exact=username)
                if not filter_result:
                    raise forms.ValidationError("手机号不存在!或未绑定手机号!")
            
            else:
                filter_result = Users.objects.filter(username__exact=username)
                if not filter_result:
                    raise forms.ValidationError(
                        "用户名不存在!")
    
            return username
    
    
    class ProfileForm(forms.Form):
        
        def __str__():
            return "你好!"
        
    class PwdChangeForm(forms.Form):
        
        def __str__():
            return "你好!"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172

    编写html

    在app中的templates文件夹下新建文件夹users,新建login.html profile.html registration.html

    login.html
    {% block content %}
    <div class="form-wrapper">
       <form method="post" action="" enctype="multipart/form-data">
          {% csrf_token %}
          {% for field in form %}
               <div class="fieldWrapper">
            {{ field.errors }}
            {{ field.label_tag }} {{ field }}
            {% if field.help_text %}
                 <p class="help">{{ field.help_text|safe }}p>
            {% endif %}
               div>
            {% endfor %}
          <div class="button-wrapper submit">
             <input type="submit" value="Submit" />
          div>
       form>
    div>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    registration.html
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        <div>
            <form method="post" action="" enctype="multipart/form-data">
               {% csrf_token %}
               {% for field in form %}
                    <div class="fieldWrapper">
                 {{ field.errors }}
                 {{ field.label_tag }} {{ field }}
                 {% if field.help_text %}
                      <p class="help">{{ field.help_text|safe }}p>
                 {% endif %}
                    div>
                 {% endfor %}
               <div>
                  <input type="submit" value="Submit" />
               div>
            form>
         div>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    profile.html
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        ??
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行

    执行命令

    python manage.py runserver
    
    • 1

    在这里插入图片描述
    在网址输入: http://127.0.0.1:8000/users/login
    在这里插入图片描述

    完毕

    前端页面待开发…
  • 相关阅读:
    仙人指路,引而不发,Go lang1.18入门精炼教程,由白丁入鸿儒,Golang中New和Make函数的使用背景和区别EP16
    基于C++的微流控生物芯片模拟程序设计
    Linux知识点 -- 网络基础(二)-- 应用层
    LDR6035智能蓝牙音响可充可放(5.9.12.15.20V)快充快放设备充电
    Jaeger系统实现对Harbor的链路追踪
    2022/09/30 echarts 简单绘图 折线图
    FS4059C ESOP8 5V升压充电12.6V三串锂电池充电IC
    数据库和数据仓库
    Mocha MemoryBufferQueue 设计概述
    HotSpot垃圾收集算法实现细节
  • 原文地址:https://blog.csdn.net/liudadaxuexi/article/details/126901052