day66 模板小结 [母板继承,块,组件]
小结:
day65 1. 老师编辑功能写完 1. magic2函数 --> 用两层for循环解决 全栈8期之殇 问题 2. 模板语言 in 语法 {% if xx in xx_list %} {% endif %} 搜索框(pymysql LIKE %) pymysql like查询 拼接占位符时注意的情况 2. Django再次入门 内容回顾 HTTP请求的本质: 1. socket server是启动的 bind((ip, port)) accept 2. 浏览器(socket 客户端)输入 域名 回车 2.1. 解析域名 -> IP和端口 --> 建立连接 2.2 发GET请求 b'GET / HTTP/1.1\r\nhost:127.0.0.1:8000\r\n\k2:v2r\n\r\n请求体' 2.3 发POST请求 b'POST / HTTP/1.1\r\nhost:127.0.0.1:8000\r\n\k2:v2r\n\r\n?name=alex&age=18' 3. 服务端 接收数据 4. 解析数据, 拿到URL、请求的方法等等 --> 处理数据 5. 给浏览器发送 响应 消息 --> b'HTTP/1.1 200 OK\r\nContent-Type:text/html; charset=utf-8\r\nk2:v2\r\n\r\n响应体' 6. 浏览器断开此次连接 Django 常用命令 django-admin startproject s8 --> 执行这条命令的目录下创建了一个项目 cd s8 python manage.py runserver IP:port (目前阶段)Django新建项目要做的事儿: settings.py 1. 注释csrf那一行 2. 配置Templates模板(HTML文件)的目录 1. 1.8版本的设置 3. 配置静态文件(js、CSS、img、插件等)的路径 1. 外号/别名 --> 在HTML页面上用 2. 静态文件存放的真实目录 Django内容: APP URLConf 3. 今日作业 1. 先把老师信息编辑功能 自己写完 2. 把URLconf今天讲到的知识点都整理好笔记,方便后面项目中遇到了快速回来查询 3. 复习之前Python的内容 Python内容: 1. 数据类型 --> int str bool list dict set tuple 流程控制 深浅拷贝 编码 2. 文件操作 --> 3. 函数 参数 返回值 作用域 调用 闭包 装饰器 迭代器 生成器 列表生成式 匿名函数 递归函数 内置函数 4. 模块和包 常用模块 自己写的python文件不要不要不要和内置模块重名 5. 面向对象 --> 三大特性 6. 异常处理 *7. 网络编程(优先级低) *8. 并发编程(优先级低 数据库: 1. 常用SQL语句 前端: form表单 Django: 创建项目 设置 APP URLConf 4. 明天内容 views和模板语言 3. 路由系统 URLConf 4. 回顾下Python都学了哪些内容
day66 1. 前情回顾 1. Django项目创建APP --> 新建Django项目就要创建一个初始APP 2. 路由系统 --> urls.py --> 映射(对应关系) 网址或URL 对应 函数 正则表达式 视图函数(处理业务逻辑) url(r'^blog/$', views.blog), url(r'blog/\d{4}/\d{1,2}', views.blog), 弊端:获取不到网址里面输入的年份和月份 url(r'blog/(\d{4})/(\d{1,2})', views.blog), 传参数:blog(request, arg1, arg2) ,相当于 调用视图函数时除request参数外,传了两个位置参数 弊端: 参数的顺序要一一对应,不能乱 url(r'blog/(?P<year>\d{4})/(?P<month>\d{1,2})', views.blog), 传参数:blog(request, year=xxxx, month=xx) inclue 网址/URL 分级处理 什么时候需要做分级处理?我们不是所有的情况都需要做分级处理, 我们先把所有的url都写到总项目里面的url文件里面,根据业务需求写的特别多不便于查找的时候,我们才会分级 url(r'^app01/', include(app01_urls)), url(r'^app02/', include(app02_urls)), 网址/URL规则命名(反向解析)给URL的正则表达式起别名 所有URL/网址写死的地方都要用反向解析 模板里面: {% url "名字写在这里"%} 视图里面: from django.urls import reverse reverse("名字", args=(1, 2)) namespace 项目里还会讲解,现在重点在理解为主。 2. 视图函数(处理业务逻辑) 和我们学过的函数都是一样的 它接受的参数,第一个参数默认就是request对象,它的返回值一定要是一个HttpResponse类型 FBV -> 把视图写成一个函数 CBV -> 把视图写成一个类 用什么方便就用什么,根据需求选择 def login(request): # 在函数中如何区分GET请求和POST请求 if request.method == "GET": # 这是GET请求 -> 获取一个页面 if request.method == "POST": # POST请求 -> 提交数据 导入基类 from django.views import View class Login(View): def dispatch(self): 在请求前和请求之后执行 hasattr("get") 等到后面讲cookie和session时候再讲(登录) def get(self, request): # 这是GET请求 def post(self, request): # POST请求 Form表单提交数据,三要素: 1. form标签的属性:action=“提交的URL地址”,method=“POST”, 不写method默认是GET请求 2. form表单里面要包含有一个submit按钮 3. input、select、checkbox、radio、textarea必须有name属性 2. request对象 request.method --->GET 或 POST 都必须要是大写 request.POST request.GET request.path request.FILES request.cookie request.session request.get_host() request.get_full_path() request.get_signed_cookie() request.is_ajax() 如果POST请求提交过来的数据某一项有多个值: 比如说: 多选的select checkbox request.POST.getlist("hobby") request.POST 里面没有文件相关内容 可以从request.body里面去看, 排错的时候我们可以打印一下我们的body里面的内容 response对象 自己生成response对象需要用到 from django.shortcuts import Httpresponse, render, redirect 最后都是return Httpresponse("这里是用来返回简单的字符串") 返回页面就用到render(request,'xx.html'{"页面在返回给前端之前把页面里面的变量填充替或替换的变量"}) redirect("/xxx_list/") 这就是我们自己写好的views函数 return JsonResponse({"k":"v}) 3. 模板语言 1. {{ 变量名 }} {{ 变量.xx }} {{dict.name}} 通过字典里面的key直接用.取value值 Django模板语言 对象.方法 就可以直接执行 不需要加() Django模板语言 对象.方法 就可以执行,不要加括号 ***** ORM 很多地方都会用到这个 2. {% for class in class_list %} {% if forloop.first %} {% endif %} {{ forloop.counter }} {{ forloop.counter0 }} {{ class }} {% if forloop.last %} {% endif %} {% endfor %} 3. {% if 判断条件 %} {% elif %} {% else %} {% endif %} 4. {% if xx in xx_list %} {% endif %} 母版继承 把所有页面共用的部分 提取出来 放到母版里面 母版里面通过定义 block , 通常模板里面为子页面单独定义 {% block page_css %}{% endblock %} --> 子页面才用到的CSS文件 {% block page_js %}{% endblock %} --> 子页面采用到的JS文件 子页面 继承 {% extends "base.html" %} *****一定放到子页面的最顶部 {% block page_main %} 我子页面才有的内容 {% endblock %} 组件 通过把独立的html内容 拿出来 放在一个单独的HTML文件中 在用到的地方用 {% include "navbar.html" %} 来导入 静态文件也需要做出变更,不能够写死 {% load static%} {% static 'img/09.jpg'%} --->/static/img/09.jpg
django模板系统
常用语法
csrf_token
我们在创建django项目的时候都是把setting里面的csrf给注释掉,这里我们可以不注释掉它
前提是要把我们的HTML文件里面的form表单里面写上{% csrf_token %}
母板
我们的前面学到的老师,班级学生管理系统,的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"> <title>Title</title> {% block page-css %} # 这里使用{% block是关键字 %} {% endblock %} # 这里就像我们的for循环里面的fro和endfor一样的,需要有开始和结束符,都是固定格式 </head> <body> <h1>这是母板的标题</h1> {% block page-main %} {% endblock %} <h1>母板底部内容</h1> {% block page-js %} {% endblock %} </body> </html>
我们一般会在母板中定义页面专用的css块和js块,方便子页面替换
继承母板,
在子页面中在页面最上方使用下面的语法来继承母板
{% extends 'layouts.html' %},我们在继承的时候可以继承块,继承组件,以及静态文件都可以
当我们使用模板继承,extends的时候,我们就相当于是直接copy了一份母板出来,就是粘贴复制的意思,我们的子页面,HTML里面就只写上上面的那一句话即可,{%extends 'login.html'%}
如果我们不想全部继承母板里面的所有内容的话我们就把不想继承的东西用块(block)包裹起来,
然后在我们的子页面里面把上面的第一句写上之后,就接着写
{%block 这里是自定义名字 %} 我们这里的block后面的名字是一个变量我们自定义即可,前提是我们的这里的变量和我们的母板里面的变量需要对应上,既然这样的话我们的母板里面有哪些内容是我们的子页面不需要继承的,我们做一个标记,把它包裹起来,这样我们的子页面就根据这个标记去对接上把相应的内容替换掉.
这个部分就是我们想要在我们的子页面里面自己写的新的代码,
{% endblock%}
我们的母板和我们的子页面需要一一对应上,也就是我们的母板里面的block块写在什么地方,我们的子页面里面的block块就插入在什么地方,如果我们想继承所有的母板里的内容,那么我们就把block块写到我们的母板的最后面,这样就可以实现直接增加的效果了.
块(block)
通过在母板中使用{% block xxx %}来定义'块'
在子页面中通过定义母板中的block名来对应替换母板中相应的内容
{% block page-main %}
<p>世情薄</p>
<p>人情恶</p>
<p>雨送黄昏花易落</p>
{% endblock %}
组件
我们的HTML页面都会有页头,页头我们也会自己做一个母板,
然后在下面的子页面中就直接继承它,
{% include 'navbar.html' %}
这里就涉及到继承关系了,我们的A是navbar.html[它本质上就是一个HTML文件,里面只有我们需要的标签内容,不是完整的HTML页面的head,body,根据需求去写它,如果只需要一句话就可以只写一句话,没头没尾的一句话也行],然后我们的B是要继承A的子页面,我们需要在B的什么地方把A加上去就放到对应的地方即可,
然后如果有C来继承B的话,比如我们的C继承了B使用{% extends 'B.html' %}的方法的话,我们想直接通过C去继承A的话,我们在C里面加上块block的继承关系,然后把A写到block里面才可以,否则因为我们使用了extends的方法,不能孤零零的直接加上include在里面,所以我们C使用block的话,就相应的在B里面把block加上跟我们的C对应上才可以达到通过C直接去继承A使用include的效果
举例说明把具体代码粘过来:
# 这里就是B <!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"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.min.css"> {% block css %} {% endblock %} </head> <body> <div class="page-header"> <h1>Example page header <small>Subtext for header</small> </h1> </div> <div class="jumbotron"> <h1>Hello, world!</h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> {% block page %} {% endblock %} {#<script src="/static/js/jquery-3.2.1.min.js"></script>#} {#{% include 'head.html' %}#} </body> </html>
# 这是A 写得比较简单,就一句话 <div > 这里是head标签里面的内容 </div>
# 这是C继承了我们的B使用的extends,然后又继承了A使用了include {% extends 'hello.html' %} {# 我们这是直接继承了我们的模板的全部内容 #} {% block css %} <style> #a {color:red} </style> {% endblock %} {% block page %} <div>雨送黄昏花易落</div> <p id="a">晓风干</p> <p>泪痕残</p> {% include 'head.html' %} # 这个include需要写到我们的block里面 {% endblock %}
关于母板,继承,块,组件的例子都是在上面,代码里面都实现了,
静态文件相关
{% load static %}我们在这里先把静态文件给load下来,
<img src='{%static "images/hi.jpg" %}' alt="Hi !"/>然后再这里引用的时候就直接使用上面load的静态文件
引用js文件时使用:
{%load static%}
<script src="{%static "mytest.js" % }"></scrippt>
某个文件多处被用到可以存为一个变量
{% load static %}
{% static 'images/hi.jpg' as myphoto %}
<img src="{{myphoto}}"></img>
我们在我们自己写好的HTML页面里面想把一个文件存成变量,然后再引用的时候写得简单一点就在django项目里面把需要使用的静态文件拿出来(这里拿出来的是最上一级的目录,就是我们的django项目里面的子目录),然后使用load语法加载到我们的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"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.min.css"> {% block css %} {% endblock %} </head> <body> <div class="page-header"> <h1>Example page header <small>Subtext for header</small></h1> </div> <div class="jumbotron"> <h1>Hello, world!</h1> <p>This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> {% block page %} {% endblock %} # 这里是我们的django项目里面的static静态文件夹它是django的子目录 {% load static %} {% static "js/jquery-3.2.1.min.js" as jquery %} # 我们的static里面还有其他的层级的目录,使用/一一写出来,直到我们找到我们需要的那个jquery文件为止. <script src="{{ jquery }}"></script> # 这里即是直接引用我们所赋值的那个变量 {#<script src="/static/js/jquery-3.2.1.min.js"></script>#} {#{% include 'head.html' %}#} <script> # 我们这里是写一段js代码来测试我们的jquery文件是否成功的引入了,如果有效果的话就是成功引入,我们的静态文件赋值给变量的操作没有bug. function time(){ $("small").each(function(){ $(this).text(""); }); } setInterval('time()',2000); </script> </body> </html>
使用get_static_prefix
{% load static%}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi !"/>
或者
{%load static%}
{% get_static_prefix as STATIC_PREFIX%}
<img src="{{STATIC_PREFIX}} images/hi.jpg" alt="Hi !" />
<img src="{{STATIC_PREFIX}}" images/hi2.jpg" alt="hello!" />
自定义simpletag
和自定义filter类似,只不过接收更加灵活的参数
定义注册simple tag
@register.simple_tag(name='plus')
def plus(a,b,c):
return "{}+{}+{}".format(a,b,c)
使用自定义simple tag
{%load app01_demo%}
{#simple tag#}
{%plus "1" "2" "abc"%}