Django学习笔记_小结(1)_留言板

环境: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>&nbsp;</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

发布了18 篇原创文章 · 获赞 0 · 访问量 577

猜你喜欢

转载自blog.csdn.net/zhsworld/article/details/103791111