IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> django安装到运行,简单的注册登录 -> 正文阅读

[Python知识库]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为项目名称

在这里插入图片描述

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

在这里插入图片描述

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

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

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

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

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

在这里插入图片描述

在这里插入图片描述

  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数据库端口号
        }
}

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

import pymysql

pymysql.install_as_MySQLdb()

在这里插入图片描述

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

在这里插入图片描述

运行

  1. 运行命令
python manage.py runserver

在这里插入图片描述

  • 浏览器打开 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}"

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

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

在这里插入图片描述

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

在这里插入图片描述

# 迁移数据库
python manage.py migrate

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

配置路由

在这里插入图片描述
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'),
]

在这里插入图片描述

编写视图函数

在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')

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

AUTHENTICATION_BACKENDS = [
    'users.utils.UsernameMobileAuthBackend',
]

编写表单校验

在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 "你好!"

编写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 %}
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>Document</title>
</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>
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>Document</title>
</head>
<body>
    ??
</body>
</html>

运行

执行命令

python manage.py runserver

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

完毕

前端页面待开发…

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:24:34  更:2022-09-21 00:27:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 10:34:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码