环境:Ubuntu18.04 + Python3.7 + Django2.2 + Mysql5.7
使用pycharm开发
第一部分 Django框架MTV简述
1、MVC是一种web开发规范
M: model,数据处理层,包括数据逻辑、数据存取等
V: view,可视化层,负责数据的显示
C:controller,控制层,负责接收和处理请求,并调用model和view响应请求
2、Django框架借鉴MVC,将框架分为Model(模型)、Template(模板)和View(视图)三部分
M :Model,模型层:负责业务对象和数据库的关系映射(ORM)
T :Template,模板层 :负责如何把页面展示给用户(html)
V :Viem,视图层:负责业务逻辑,并在适当时候调用Model和Template
第二部分 Django项目简述
1、创建项目
django-admin startproject Message
2、创建应用
python manage.py startapp message_form
3、注册应用
# settings.py 文件
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'apps.message_form.apps.Message_formConfig', # 新增
]
4、补充创建文件夹后,Django完整目录及功能说明
Message/
apps/ # 存放自建的应用
message_form/ # 自建的第一个应用
migrations/ # 负责数据库迁移操作。makemigrations命令将model层转为迁移文件,migrate命名将新版本的迁移文件执行,更新数据库
__init__.py
admin.py # 对应应用的后台管理配置文件
apps.py # 对应应用的配置文件
models.py # 模型层,负责描述数据,一般情况下,每个模型对应数据库中的一张表
tests.py # 自动化测试模块
views.py # 视图层,负责处理用户的请求并返回响应
__init__.py
extra_apps/ # 存放第三方的应用
media/ # 存放用户上传的文件
Message/
__init__.py
settings.py # 全局配置文件
urls.py # 路由设置,当用户请求访问Django站点时,负责决定执行哪个视图函数
asgi.py # 异步网关协议接口,是wsgi的扩展,支持Websocket。初学者一般不用设置
wsgi.py # Web服务器网关接口,负责解决Web服务器端与客户端之间的通信问题。初学者一般不用设置
static/ # 存放静态文件,包括css,图片等
template/ # 存放前端页面
manage.py # 管理 Django 项目的命令行工具
requirements.txt # 记录依赖的包
5、启动服务
python manage.py runserver
第三部分 Django简易开发流程
以单页面留言板开发为例
1、业务分析
访问时表单显示数据库中的某些默认数据,提交后表单显示提交的数据
2、开发实践
1)model设计
1.1 在mysql中新建数据库:maxonlie
1.2 在settings.py配置mysql数据库
# 第一步
# 在Message/settings.py中将数据库配置为mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'maxonline', # 数据库名称
'USER': 'root', # 数据库用户名
'PASSWORD': '19941028', # 使用的数据库密码
'HOST': '', # 数据库主机,留空默认为localhost
'PORT': '3306', # 据库端口
}}
# 第二步
# mysql的默认引擎为MySQLdb,MySQLdb并不支持python3.x,所以需要替换成pymysql
# 在主配置文件目录(与项目同名)的Message/__init__.py中导入pymysql
import pymysql
pymysql.install_as_MySQLdb() # 当成是mysqldb一样使用
1.3 设计数据结构
# apps/models.py文件
from django.db import models # 默认有
# 定义一个Model类
class Message(models.Model):
# 定义四个字段姓名、邮箱、地址、留言
name = models.CharField(max_length=20, verbose_name="姓名", primary_key=True)
email = models.EmailField()
address = models.CharField(max_length=100, verbose_name="地址")
message = models.TextField(verbose_name="留言")
# CharField(类似于mysql中的varchar,需要接收一个 max_length 参数,用以指定数据库存储数据时用的字节数)、TextField(类似于mysql中的longtext)、EmailField是字段类型
# 更多字段类型可参考 https://docs.djangoproject.com/zh-hans/2.2/ref/models/fields/#field-types
# verbose_name 字段备注名,类似于mysql的注释
# primary_key,如果设置为 True ,将该字段设置为该模型的主键。在一个模型中,如果没有对任何一个字段设置 primary_key=True 选项。 Django 会自动添加一个 IntegerField 字段,并设置为主键
class Meta:
# 定义表名
db_table = "message"
# 定义表按什么字段排序
ordering = ['-name'] # 按姓名排列,-表示降序
# 定义在管理后台显示的名称
verbose_name = '留言'
# 定义复数时的名称(去除复数的s)
verbose_name_plural = verbose_name
#更多 Meta 选项可参考 https://docs.djangoproject.com/zh-hans/3.0/ref/models/options/#
1.4 更新数据库
# 打包成迁移文件
python manage.py makemigrations
# 执行迁移(更新数据库)
python manage.py migrate
2)views设计
参考1:对model操作的一些基本方法
# 对model进行操作(QuerySet)
# QuerySet 支持链式调用
# QuerySet 是惰性的,创建时不会执行任何操作
# all(),取所有的数
# 支持for循环和切片两种操作
all_messages = Message.objects.all()
# for message in all_message:
# print(message.name)
# sliced_query = Message.objects.all()[:1]
# 支持的Field lookups的三个函数filter()、exclude()、get()
# exclude:filter函数取反
# get():只返回一条查询到的数据,如果数据不存在,或者数据存在多条,则会抛出异常
# filter(),筛选数据
filter_messages = Message.objects.filter(name__exact="zhs") # 精确等于,__exact可省略
filter_messages = Message.objects.filter(name__contains="zhs") # 类似于mysql中的like"%zhs%"
# iexact忽略大小写的等于,gte ≥,startswith 类似于like"zhs%",regex 支持正则,in,range等
# 更多筛选条件可参考 https://docs.djangoproject.com/zh-hans/2.2/ref/models/querysets/#field-lookups
# delete(),数据删除
all_messages = Message.objects.filter(name="zhs")
all_messages.delete() # 删除出批量数据
for message in all_messages:
print(message.name)
message.delete() # 删除单条数据
# 插入数据,类似于mysql的insert
# 实例化类
message = Message()
# 为实例赋值
message.name = "zhs1"
message.email = "[email protected]"
message.address = "hebei"
message.message = "hello word"
# 保存
message.save()
# order_by():数据排序
# 更多QuerySet API可参考https://docs.djangoproject.com/zh-hans/2.2/ref/models/querysets/#queryset-api
参考2:render函数
render(request, template_name, context=None, content_type=None, status=None, using=None)
# request: 用于生成此响应的请求对象
# template_name: 要使用的模板的全名或模板名称的序列
# context: 要添加到模板上下文的值的字典
# 更多可参考 https://docs.djangoproject.com/zh-hans/2.2/topics/http/shortcuts/#render
参考3:urls调度器
# Django依次匹配每个URL模式,在与请求的URL匹配的第一个模式停下来
# 支持path和re_path(正则)两种匹配模式
# 匹配示例
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]
# 需要注意的是
# 1 开头不需要添加反斜杠。比如,应该是articles,而不是/articles
# 2 要从URL中取值,使用尖括号<>
/articles/2005/03/ # 会匹配URL列表中的第三项。Django会调用函数views.month_archive(request, year=2005, month=3)
/articles/2003/ # 会匹配URL列表中的第一项,而不是第二项。Django会调用函数views.special_case_2003(request)
/articles/2003 # 不会匹配URL列表中到任意一项
/articles/2003/03/building-a-django-site/ # 会匹配URL列表中的最后一项。Django 会调用函数 views.article_detail(request, year=2003, month=3, slug="building-a-django-site")
#str:匹配除'/'之外的非空字符串
#int:匹配0或任何正整数。返回一个int
#slug:匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,building-your-1st-django-site 。
#uuid:匹配一个格式化的UUID。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例
#path:匹配非空字段,包括路径分隔符 '/' 。它允许你匹配完整的URL路径而不是像 str 那样只匹配 URL 的一部分。
# 更多urls配置可参考 https://docs.djangoproject.com/zh-hans/2.2/topics/http/urls/
2.1 编写view逻辑
# views.py文件
from django.shortcuts import render # 默认有
# 导入自定义的model类
from apps.message_form.models import Message
# 自定义view方法
# message_form.html是与该方法对应的前端页面
def message_form(request):
# 如果请求类型是GET
# 假设要默认显示一些数据
if request.methon == "GET":
var_dict={}
all_messages = Message.objects.filter(name = "默认姓名")
# 如果能查询到数据,也就是all_messages不为空
if all_messages:
message = all_messages[0] # 第一条数据
var_dict = {"message": message}
return render(request, "message_form.html", var_dict)
# 如果请求类型是POST,就是提交留言时候的操作
if request.method == "POST":
name = request.POST.get("name","") # 如果确实则是空
address = request.POST.get("address", "")
email = request.POST.get("email", "")
message_txt = request.POST.get("message", "")
message = Message()
message.name = name
message.address =address
message.email =email
message.message= message_txt
message.save()
# 提交后,在页面显示提交的内容
return render(request, "message_form.html", {"message": message})
2.2 配置url
from django.contrib import admin # 默认导入
from django.urls import path # 默认导入
# 导入视图views文件中的类
from apps.message_form.views import message_form
urlpatterns = [
path('admin/', admin.site.urls), # 默认配置
path('message_form/', message_form),
]
3)template设计
理论上template设计应该在view设计前面,但本人对前端不熟悉,所以放后边了
参考1:css form表单 https://www.cnblogs.com/mr-wuxiansheng/p/6219847.html
参考2:前端 html 完整代码
html教程:https://www.runoob.com/html/html-tutorial.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<form action="/message_form/" method="post" class="smart-green">
<h1>留言信息
<span>请留下你的信息.</span>
</h1>
<label>
<span>姓名 :</span>
<input id="name" type="text" value="{{message.name}}" name="name" class="error" placeholder="请输入您的姓名"/>
<div class="error-msg"></div>
</label>
<label>
<span>邮箱 :</span>
<input id="email" type="email" value="{{message.email}}" name="email" placeholder="请输入邮箱地址"/>
<div class="error-msg"></div>
</label>
<label>
<span>联系地址 :</span>
<input id="address" type="text" value="{{message.address}}" name="address" placeholder="请输入联系地址"/>
<div class="error-msg"></div>
</label>
<label>
<span>留言 :</span>
<textarea id="message" name="message" placeholder="请输入你的建议"></textarea>
<div class="error-msg"></div>
</label>
<div class="success-msg"></div>
<label>
<span> </span>
<input type="submit" class="button" value="提交"/>
</label>
{%csrf_token%}
</form>
</body>
</html>
参考3:css 内部样式表
css 教程 https://www.runoob.com/css/css-intro.html
<head>
<style type="text/css">
body {background-color:yellow;}
p {color:blue;}
</style>
</head>
参考4:css 外部样式表
<head>
<link rel="stylesheet" type="text/css" href="mystyle.css">
</head>
<!--
rel 属性规定当前文档与目标 URL 之间的关系。仅在 href 属性存在时使用
stylesheet 文档的外部样式表,contents 文档目录
type 属性规定链接中指向的文档的 mime 类型。仅在 href 属性存在时使用
MIME(“Multipurpose Internet Mail Extensions”)是一种标准,用来表示文档、文件或字节流的性质和格式
href 属性规定链接的目标地址
-->
参考5:css 完整代码
.smart-green {
margin-left: auto;
margin-right: auto;
max-width: 500px;
background: #F8F8F8;
padding: 30px 30px 20px 30px;
font: 12px Arial, Helvetica, sans-serif;
color: #666;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
}
.smart-green h1 {
font: 24px "Trebuchet MS", Arial, Helvetica, sans-serif;
padding: 20px 0px 20px 40px;
display: block;
margin: -30px -30px 10px -30px;
color: #FFF;
background: #9DC45F;
text-shadow: 1px 1px 1px #949494;
border-radius: 5px 5px 0px 0px;
-webkit-border-radius: 5px 5px 0px 0px;
-moz-border-radius: 5px 5px 0px 0px;
border-bottom: 1px solid #89AF4C;
}
.smart-green h1 > span {
display: block;
font-size: 11px;
color: #FFF;
}
.smart-green label {
display: block;
margin: 0px 0px 5px;
}
.smart-green label > span {
float: left;
margin-top: 10px;
color: #5E5E5E;
}
.smart-green input[type="text"], .smart-green input[type="email"], .smart-green textarea, .smart-green select {
color: #555;
height: 30px;
line-height: 15px;
width: 100%;
padding: 0px 0px 0px 10px;
margin-top: 2px;
border: 1px solid #E5E5E5;
background: #FBFBFB;
outline: 0;
-webkit-box-shadow: inset 1px 1px 2px rgba(238, 238, 238, 0.2);
box-shadow: inset 1px 1px 2px rgba(238, 238, 238, 0.2);
font: normal 14px/14px Arial, Helvetica, sans-serif;
}
.smart-green textarea {
height: 100px;
padding-top: 10px;
}
.smart-green .button {
background-color: #9DC45F;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-border-radius: 5px;
border: none;
padding: 10px 25px 10px 25px;
color: #FFF;
text-shadow: 1px 1px 1px #949494;
}
.smart-green .button:hover {
background-color: #80A24A;
}
.error-msg{
color: red;
margin-top: 10px;
}
.success-msg{
color: #80A24A;
margin-top: 10px;
margin-bottom: 10px;
}
3.1 将css文件单独存放时需注意,需注意
- 存放在主目录的static文件夹中
- 配置settings.py文件中static的路径
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
3.2 从前端表单中提取数据,保存到数据库时,需注意
- 调整<form action="/message_form/" method="post" class="smart-green">中的action路径
- 在<form>标签的最后添加验证{%csrf_token%}
csrf(Cross Site Request Forgery, 跨站域请求伪造)攻击是黑客借助受害者的cookie骗取服务器的信任,但是黑客并不能拿到cookie,也看不到cookie的内容,详细可参考https://www.ibm.com/developerworks/cn/web/1102_niugang_csrf/#icomments
3.3 从数据库中提取数据,显示到前端表单时,需注意
- value的正确语法是{{ }}:value="{{message.name}}"
end