一、Django简介
Django 是一个开源免费的Python 框架,可以更轻松地使用 Python 创建网站,是 Python 社区的两大最受欢迎的 Web 框架之一(另一个是 Flask)。Django 会处理困难的事情,以便您可以快速开发可维护和可扩展的 Web 应用程序。
Django 强调组件的可重用性,也称为 DRY(不要重复自己),并带有登录系统、数据库连接和 CRUD 操作(创建读取更新删除)等即用型功能。Django 对于数据库驱动的网站特别有用。前端仍需要借助流行的JS框架如Vue.js才能开发出互动性强且符合未来审美趋势的优秀网站来。
Django 本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。
Django给开发者提供的模型是MTV,MTV 模式本质上和 MVC 是一样的,也是为了各组件间保持松耦合关系。
M 表示模型(Model):编写程序应有的功能,负责业务对象与数据库的映射(ORM)。和MVC中的Model能力一致。
T 表示模板 (Template):负责如何把页面(html)展示给用户。和MVC模式中的View一致。
V 表示视图(View):负责业务逻辑,并在适当时候调用 Model和 Template。与MVC结构中的Controller一致。

二、从0搭建Django环境,开发登录注册功能 - 20分钟学会Django Web开发
2.1 Django 安装
没错,最简单的pip安装即可!

2.2 创建第一个项目
没错,一行命令就可以创建一个项目!

一行命令就可以启动Web服务!
注:类似于Java,需要使用Tomcat容器,Django自带了一个简单的Run Server,可以作为Web应用的容器)

注:自动生成项目的目录说明:
python_web: 项目的根目录。
manage.py: 自动生成的项目管理脚本,一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
python_web/__init__.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
python_web/asgi.py: 一个 ASGI 兼容的 Web 服务器的入口,以便运行你的项目。
python_web/settings.py: 该 Django 项目的设置/配置。
python_web/urls.py: 该 Django 项目的 URL 声明,一份由 Django 驱动的网站"目录"。
python_web/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。

2.3 创建并配置应用程序
Django的一个项目(project)是可以包含多个应用(app),应用是在您的项目中具有特定含义的网络应用程序,如注册登录、网络通信、会议视频等。
本文中就以一个注册登录功能的应用为例,还是一条命令生成应用框架。


2.4 MTV架构解析

2.4.1 M 模型(Model):模型提供来自数据库的数据
Django 是一个成熟的强大 Web 框架,支持PostgreSQL、MariaDB、MySQL、Oracle 和 SQLite等数据库,本示例就以互联网大厂中最流行的MySQL数据库为例。
- 安装MySQL
1)官网*载下**社区版,免费使用

2)按照安装向导进行安装

3)配置MySQL


4)检查安装状态

5)设置环境变量,方便使用命令行方式运行命令



- 创建并配置数据库
1)语法
CREATE DATABASE [IF NOT EXISTS] <数据库名>
[[DEFAULT] CHARACTER SET <字符集名>]
[[DEFAULT] COLLATE <校对规则名>];
<数据库名>:创建数据库的名称。MySQL 的数据存储区将以目录方式表示 MySQL 数据库,因此数据库名称必须符合操作系统的文件夹命名规则,不能以数字开头,尽量要有实际意义。注意在 MySQL 中不区分大小写。
IF NOT EXISTS:在创建数据库之前进行判断,只有该数据库目前尚不存在时才能执行操作。此选项可以用来避免数据库已经存在而重复创建的错误。
[DEFAULT] CHARACTER SET:指定数据库的字符集。指定字符集的目的是为了避免在数据库中存储的数据出现乱码的情况。如果在创建数据库时不指定字符集,那么就使用系统的默认字符集。
2)登录MySQL并创建DB


3)setting.py中配置MySQL连接设置

- 编写模型代码, 并创建数据库
1)Login_demo/modes.py,编写模型代码
from django.db import models
class Users(models.Model):
username = models.CharField(max_length = 666)
password = models.CharField(max_length= 666)
mobile = models.CharField(max_length = 666)
gender = models.CharField(max_length = 8)
registerTime = models.DateTimeField(auto_now_add = True)
2)使用命令行,基于modes.py创建数据库表结构和字段
#使数据库状态与当前模型集和迁移集同步
PS D:\python_web\python_web> python manage.py migrate
#Django会去检查创建或修改数据库,如果不合法会给出提示
PS D:\python_web\python_web> python manage.py makemigrations login_demo
#创建表结构,执行完makemigrations只是生成了对应的sql语句,还并没真正将改动迁移到数据库中。
#需要执行migrate才能将改动迁移到数据库,完成建表、修改字段等操作。
PS D:\python_web\python_web> python manage.py migrate login_demo


3)验证表明和字段
MySQL 会把我们的数据详情存储在 information_schema 这个系统数据库中, 我们可以从中查询并验证数据库和表信息。



2.4.2 V 视图(View):负责业务逻辑控制
- 路由设计
当URL请求从端侧到达服务,路由是用来区分将请求分发到那个模型,那个页面。
1)路由规则
当用户未登录:进入login界面,对应界面 login.html
用户登录成功:跳转到index界面, 对应界面 index.html
点击注册:跳转到register页面, 对应界面 register.html
点击登出:挑战到login界面,对应界面login.html
验证码:使用python开源简单验证码应用,直接引用captcha.urls
2)路由配置

3)View按照路由规则进行逻辑判断,存储/查询数据,以及分发请求
用户登录:查询数据库进行用户名和密码对比
用户注册:存储用户数据到数据库
Views方法定义(示例完整代码参考文末):

2.4.3 T 模板 (Template):负责如何把页面(html)展示给用户
- 模版的基本语法
1) {{ }} 括号内呈现变量(包括视图或本地定义变量)
例如:<h1>{{ username}}, 欢迎回家</h1>
2){% with %])模板中创建变量
例如:{% with username="ShanGouXueHui" %}
3) 模板标签(可以执行编程逻辑)
为了执行模板标签,需将之放在 {% %} 括号中,例如:
<ul>
{% for x in range(5)%}
<li>{{ x}}</li>
{% endfor %}
</ul>
Autoescape:指定自动转义模式是打开还是关闭
Block:指定一个块部分
Comment:指定注释部分
csrf_token:保护表单免受跨站请求伪造
Cycle:指定要在循环的每个循环中使用的内容
Debug:指定调试信息
Extends:指定一个父模板
Filter:在返回之前过滤内容
Firstof:返回第一个非空变量
For:指定一个for循环
If:指定一个 if 语句
Ifchanged:用于 for 循环。 仅当自上次迭代以来值已更改时才输出块
Include:指定包含的内容/模板
Load:从另一个库加载模板标签
Lorem:输出随机文本
Now:输出当前日期/时间
Regroup:按组对对象进行排序
Resetcycle:循环使用。 重置循环
Spaceless:去除 HTML 标签之间的空格
templatetag :输出指定的模板标签
Url:返回 URL 的绝对 URL 部分
Verbatim:指定不应由模板引擎呈现的内容
Widthratio:根据给定值和最大值之间的比率计算宽度值
With:指定要在块中使用的变量
4)Extends扩展标签,使用覆膜板简化HTML
extends 标签给当前模板添加父模板。这样就可以套用同一个母版页,搭建页面框架。
Django 使用 {% block %} 标签来创建占位符。
5)过滤器
过滤器标签允许您在返回值之前通过过滤器运行一个值。使用管道 | 字符后跟过滤器名称来指定过滤器。过滤器的名称定义了过滤器将如何处理值。
6)include 包含标签
include 标签可以在当前模板中包含一个模板。当内容块在许多页面上都相同时,就可以通过include完成复用。

- 模版定义
Web界面开发离不开HTML,CSS,JS等技术和相应的开源库,为聚焦MTV主线,本文不做赘述。样例仅使用简单标签,并给了详细注释,不会影响演示、交流。
名称需要与urls.py中配置保持一致。

三、Django Web开发示例 - 注册登录源码与演示
- 源码(系统自动生成的,未修改的文件不再单列)
1)python_web/settings.py - 配置应用,数据库
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-ej+ed-#6d6u(w__dz)xnrrew2z#3b)#(^v^yq#c8&!)clni8zl'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#自定义登录应用,在此注册
'login_demo',
#python自带简单验证码应用,提前安装配置:pip install django-simple-captcha
#'captcha',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'python_web.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'python_web.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
DATABASES = {
'default': {
#配置数据库引擎
'ENGINE': 'django.db.backends.mysql',
#配置数据库名,预先创建
'NAME': 'login_demo',
# 用户名,可以自己创建用户
'USER': 'root',
# 密码
'PASSWORD': 'hello@1',
# mysql服务所在的主机ip
'HOST': '127.0.0.1',
# mysql服务端口
'PORT': '3306',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
2) python_web/login_demo/models.py - 定义模型,用于与数据库交互
from django.db import models
class Users(models.Model):
username = models.CharField(max_length = 666)
password = models.CharField(max_length= 666)
mobile = models.CharField(max_length = 666)
gender = models.CharField(max_length = 8)
registerTime = models.DateTimeField(auto_now_add = True)
3) python_web/login_demo/views.py - 编写控制逻辑代码
from django.shortcuts import render
from django.shortcuts import redirect
from . import models
def index(request):
#local()是Python中的一个内置函数,它可以将函数中的局部变量以字典的形式返回。
#生产环境中,需要显示指定哪些变量值返回,否则可能会造成数据泄露
return render(request, 'index.html', locals())
def login(request):
#如果用户已经登录,则直接跳转
if request.session.get('isLogin', None):
return redirect('/index/')
if request.method == 'POST':
username = request.POST.get('username')
#生产环境中密码需要加密,为了主线简介,本例子暂不演示
password = request.POST.get('password')
#如果用户名和密码不为空,真实场景可以增加更多格式验证。
message = '用户或密码错误,请输入正确的信息!'
if username.strip() and password:
try:
#通过models查询数据库,免写sql语句,使用对象访问即可
user = models.Users.objects.get(username=username)
if user.password == password:
#登录成功后在session字典内写入用户状态;session里面写任何数据,不仅仅限于用户相关!
request.session['isLogin'] = True
return redirect('/index/')
else:
return render(request, 'login.html', {'message': message})
except:
return render(request, 'login.html', {'message': message})
else:
return render(request, 'login.html', {'message': message})
return render(request,'login.html')
def register(request):
#如果用户已经登录,则直接跳转
if request.session.get('isLogin', None):
return redirect('/index/')
message = '请检查输入数据,是否合适!'
if request.method == 'POST':
username = request.POST.get('username')
#生产环境中密码需要加密,为了主线简介,本例子暂不演示
password1 = request.POST.get('password1')
password2 = request.POST.get('password2')
#生产环境中数据需要判断格式,一般使用正则表达式完成,本例子暂不赘述
gender = request.POST.get('gender')
mobile = request.POST.get('mobile')
user = ''
if username.strip() and password1 and (password1 == password2):
try:
#通过models查询数据库,免写sql语句,使用对象访问即可
user = models.Users.objects.get(username=username)
except:
pass
if user:
message = '用户名已存在,请重新输入'
return render(request, 'register.html', {'message': message})
else:
#通过models模版将数据写入数据库,可以避免sql,直接用对象做操作
newUser = models.Users()
newUser.username = username
newUser.password = password1
newUser.gender = gender
newUser.mobile = mobile
newUser.save()
#注册成功后,转入登录界面
return redirect('/')
else:
return render(request, 'register.html', {'message': message})
#local()是Python中的一个内置函数,它可以将函数中的局部变量以字典的形式返回。
#生产环境中,需要显示指定哪些变量值返回,否则可能会造成数据泄露
return render(request, 'register.html', locals())
def logout(request):
print(index, 'logout--------------------')
#如果用户已登录,则清空session,否则直接跳转
if request.session.get('isLogin', True):
request.session.flush()
return redirect('/')
# username = models.CharField(max_length = 666)
# password = models.CharField(max_length= 666)
# mobile = models.CharField(max_length = 666)
# gender = models.CharField(max_length = 8)
# registerTime = models.DateTimeField(auto_now_add = True)
python_web/urls.py - 请求路由配置
from django.contrib import admin
from django.urls import path, include
from login_demo import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.login),
path('index/', views.index),
path('register/', views.register),
path('logout/', views.logout),
#python开源验证码包
#path('captcha/', include('captcha.urls'))
]
4)python_web/login_demo/templates - 定义模版,用于显示界面
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--title标签定义标题-->
<title>登录</title>
</head>
<body>
<!--div标识图层,将登录块隔离出来,方面集中控制格式,CSS margin(外边距)属性定义元素周围的空间。-->
<div style="margin:auto">
<!--h1标签定义标题-->
<h1>欢迎登录!</h1>
<!--标签主要确定目的地url和发送方法-->
<form action="/" method="post">
<!--python自带CSRF验证-->
{% csrf_token %}
<!--显示提示信息,与return render(request, 'register.html', {'message': message})中message相应-->
{% if message %}
<p style="color:red"> {{ message }} </p>
{% endif %}
<!--p标签将各个输入框分行-->
<p>
<!--label标签为每个输入框提供一个前导提示-->
<label for="username_desc">用户名:</label>
<!--input生成一个用户输入框,placeholder属性为输入框提供占位符,
autofocus属性为用户名输入框自动聚焦,
required表示该输入框必须填写, 与view中request.POST.get('username')对应-->
<input type="text" id="username" name="username" placeholder="用户名" autofocus required />
</p>
<p>
<!--passowrd类的input标签不会显示明文密码-->
<label for="id_password">密码:</label>
<!--与view中request.POST.get('password')对应-->
<input type="password" id="passowrd" placeholder="密码" name="password" required >
</p>
<input type="submit" value="登录">
<!--新用户注册,可以通过超级链接跳转至注册用户-->
<a href="/register/" ><ins>注册</ins></a>
</form>
</div>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--title标签定义标题-->
<title>注册为新用户吧</title>
</head>
<body>
<!--div标识图层,将登录块隔离出来,方面集中控制格式,CSS margin(外边距)属性定义元素周围的空间。-->
<div style="margin:auto">
<!--标签主要确定目的地url和发送方法-->
<form action="/register/" method="post">
<!--python自带CSRF验证-->
{% csrf_token %}
<!--显示提示信息,与return render(request, 'register.html', {'message': message})中message相应-->
{% if message %}
<p style="color:red"> {{ message }} </p>
{% endif %}
<!--p标签将各个输入框分行-->
<p>
<!--label标签为每个输入框提供一个前导提示-->
<label for="id_username">用户名:</label>
<!--input生成一个用户输入框,placeholder属性为输入框提供占位符,
autofocus属性为用户名输入框自动聚焦,
required表示该输入框必须填写, 与view中request.POST.get('username')对应-->
<input type="text" id="username" name="username" placeholder="用户名" autofocus required />
</p>
<p>
<!--passowrd类的input标签不会显示明文密码-->
<label for="password1">密 码:</label>
<!--与view中request.POST.get('password1')对应-->
<input type="password" id="passowrd1" placeholder="密码" name="password1" required >
</p>
<p>
<!--passowrd类的input标签不会显示明文密码-->
<label for="password2">密码验证:</label>
<!--与view中request.POST.get('password2')对应-->
<input type="password" id="passowrd2" placeholder="密码" name="password2" required >
</p>
<p>
<!--label标签为每个输入框提供一个前导提示-->
<label for="id_gender">性 别:</label>
<!--input生成一个用户输入框,placeholder属性为输入框提供占位符与view中request.POST.get('gender')对应-->
<input type="text" id="gender" name="gender" placeholder="性别"/>
</p>
<p>
<!--label标签为每个输入框提供一个前导提示-->
<label for="id_mobile">手机号码:</label>
<!--input生成一个用户输入框,placeholder属性为输入框提供占位符与request.POST.get('mobile')对应-->
<input type="text" id="mobile" name="mobile" placeholder="手机号码"/>
</p>
<input type="submit" value="注册">
<a href="/" ><ins>直接登录</ins></a>
</form>
</div>
</body>
</html>
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--title标签定义标题-->
<title>您已成功登录</title>
</head>
<body>
<!--div标识图层,将登录块隔离出来,方面集中控制格式,CSS margin(外边距)属性定义元素周围的空间。-->
<div style="margin:auto">
<!--python自带CSRF验证-->
{% csrf_token %}
<!--标签主要确定目的地url和发送方法-->
<form action="/index/" method="post">
<p style="color:blue">您已成功登录</p>
</form>
</div>
</body>
</html>
- 结果验证
1)启动login_demo
PS D:\python_web\python_web> python .\manage.py runserver 127.0.0.1:9000
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
March 10, 2024 - 17:47:20
Django version 5.0.3, using settings 'python_web.settings'
Starting development server at http://127.0.0.1:9000/
Quit the server with CTRL-BREAK.
[10/Mar/2024 17:47:42] "GET / HTTP/1.1" 200 1808
Not Found: /favicon.ico
[10/Mar/2024 17:47:43] "GET /favicon.ico HTTP/1.1" 404 2536
2) 默认登录界面(http://127.0.0.1:9000),与urls.py中配置一致


3)注册新用户
操作流程:点击注册-->跳转到注册用户 --> 提交后成功注册 -->跳转到登录页面




4)检查数据库记录

完整工程源码:https://github.com/ShanGouXueHui/PythonBasicCases
##山狗学会 License Start##
转载请注明出处,"*今条头日**"创作者"山狗学会“ ,注明出处即授权,未注明出处罚款100万元
主页链接:山狗学会主页
##山狗学会 License End##
