![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
昨日内容回顾 路由层 路由匹配 url(正则表达式,视图函数内存地址) 只要正则匹配到了内容,就不再继续往下匹配,而是直接后面的视图函数 匹配首页 url(r'^$',home) 匹配尾页 url(r'',errors) 路由匹配的规律 第一次按照用户输入什么就匹配什么如果匹配不上 第二次django会让浏览器自动再尾部加斜杠再次匹配 还匹配不上就会报错 上述规律不是浏览器的特点,是django的功能 django settings文件中 APPEND_SALSH = True # 自动加斜杠 """为什么setting文件中变量名必须写全大写""" 无名分组 路由匹配成功之后,如果正则表达式中有分组的,那么在调用视图函数的时候 会将括号内正则表达式匹配到的内容当做位置参数传递给后面的视图函数 url(r'^index/(\d+)/',index) def index(request,args): return 'HttpResponse对象' 有名分组 路由匹配成功之后,如果正则表达式中有分组并且起了别名的,那么在调用视图函数的时候 会将括号内正则表达式匹配到的内容当做关键字参数传递给后面的视图函数 url(r'^index/(?P<year>\d+)/',index) def index(request,year): return 'HttpResponse对象' 无名分组与有名分组不能混合使用(*****) 但是两者单独使用的时候可以有多个无名或者有名 反向解析 由来当有很多html页面和后端代码中频繁的使用了指名道姓的ulr(/index/) 那么一旦路由发生了变化 前后端所有的地方都要修改,造成了可维护性较差 反向解析的本质就是通过某个方法获取的一个能够访问对应url的结果 没有涉及到正则表达式符号情况下 url(r'^index/',index,name='aaa') 前端 {% url 'aaa' %} 后端 from django.shortcuts import HttpResponse,render,redirect,reverse _url = reverse('aaa') 无名和有名分组的情况 无名 url(r'^index/(\d+)/',index,name='bbb') 前端 {% url 'bbb' 1 %} 后端 _url = reverse('aaa',args=(1,)) 有名 url(r'^index/(?P<edit_id>\d+)/',index,name='bbb') 前端 {% url 'bbb' 1 %} # 支持无名的写法 {% url 'bbb' year=1 %} 后端 _url = reverse('aaa',args=(1,)) # 支持无名的写法 _url = reverse('aaa',kwargs={'year':1}) 路由分发 include() django中的每一个app都可以有自己独立的urls.py,static静态文件夹,templates模板文件夹 正是基于上面的特点,django就可以很好的支持多人分组开发,每个人只需要开发各自的app即可 最后只需要创建一个空的django项目,将所有人的app注册进来,总路由中来一个路由分发就可以将多个人的功能整合到一个项目中 当项目比较巨大的时候 如果不使用路由分发 那么中路由的中url代码太多了 不利于维护和更新 from app01 import urls as app01_urls from app02 import urls as app02_urls url(r'应用名前缀/',include(app01_urls)) url(r'应用名前缀/',include(app02_urls)) # 推荐使用下面的方式 url(r'应用名前缀/',include('app01.urls')) url(r'应用名前缀/',include('app02.urls')) """路由分发需要注意的点 1.总路由的中最后千万不要加$符号 """ 名称空间 你在起别名的时候 虽然能够同一个应用下不能重名 但是你没办法实现多个人多个app不重名的情况 一旦重名反向解析并不能自动识别所在的应用 # 总路由中 给每一个应用开设一个名称空间 url(r'应用名前缀/',include('app01.urls',namespace='app01')) url(r'应用名前缀/',include('app02.urls',namespace='app02')) # 子路由 url(r'^index/',index,name='aaa') url(r'^index/',index,name='aaa') # 反向解析的时候 reverse('app01:aaa') reverse('app02:aaa') {% url 'app01:aaa' %} {% url 'app02:aaa' %} # 其实你可以完全不使用名称空间 只需要保证别名不重复 # 你可以在起别名的时候给每一个别名加上所在应用名的前缀 伪静态 就是url后面加了个.html 虚拟环境 不用的项目应该有属于该项目独有的python解释器环境 这样的话可以避免资源浪费以及版本兼容的问题 # 注意虚拟环境虽然好用,但是不要无限制开设 如果你机器上虚拟环境 你可以手动删除 django版本区别 路由2.X里面的是path 第一个参数不再支持正则表达式 写什么就匹配什么 如果你还想使用正则 2.X里面的re_path就是1.X里面的url 虽然path不支持正则,但是它提供了五种转化器(可以将路由匹配到的内容自动转换成对应的数据格式再传递给后面的视图函数) 除了五种转化器之外 你还可以自定义转换器 视图层 如果一个应用下的视图函数特别特别多 你可以新建一个views文件夹,然后根据功能的不同起不同名字的py文件存放不同的功能 实现持续的解耦 可读性 views user.py account.py order.py ... 三板斧 前后端分离 JsonResponse(data,safe=False,json_dumps_params={'ensure_ascii':False}) 如果你传递的不是字典数据,那么需要手动指定safe=False form表单上传文件 需要注意的实现 1.method必须是post 2.enctype必须要指定成formdata 3.目前需要考虑的 需要将settings配置文件中的csrf中间件注释掉 后端不再通过request.POST获取文件数据,而是通过request.FILES file_obj = request.FILES.get('myfile') file_obj.name # 文件名 with open(file_obj.name,'wb') as f: for chunk in file_obj.chunks(): f.write(chunk) request方法总结 request.method request.GET request.POST request.FILES request.body # 原生的二进制数据 """ RBAC (role based access control) 基于角色的权限管理 当你在做权限管理的时候 需要用到 在web领域权限就是一个个的url 简单判断用户是否有权限访问某个url思路 获取用户想要访问的url 与数据库中该用户可以访问的url进行对比 """ request.path # 只拿url request.get_full_path() # url+?后面的参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
今日内容 三板斧 render返回一个html页面 并且还能够给该页面传数据 render内部原理 from django.template import Template,Context def index(request): temp = Template('<h1>{{ user }}</h1>') con = Context({"user":{"name":'jason',"password":'123'}}) res = temp.render(con) print(res) return HttpResponse(res) FBV与CBV 视图函数并不只是指函数 也可以是类 FBV(基于函数的视图) 面向函数式编程 CBV(基于类的视图) 面向对象式编程 # 问题:基于CBV的视图函数 """get请求来就会走类里面get方法,post请求来就会走类里面post方法 为什么???""" 闭包+反射 urls.py中 url(r'^login/',views.MyLogin.as_view()) views.py中 from django.views import View class MyLogin(View): def get(self,request): print("from MyLogin get方法") return render(request,'login.html') def post(self,request): return HttpResponse("from MyLogin post方法") 研究方向 1.从url入手 url(r'^login/',views.MyLogin.as_view()) 由于函数名加括号执行优先级最高,所以这一句话一写完会立刻执行as_view()方法 @classonlymethod def as_view(cls, **initkwargs): # cls就是我们自己的写的类 MyLogin def view(request, *args, **kwargs): self = cls(**initkwargs) # 实例化产生MyLogin的对象 self = MyLogin(**ininkwargs) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request self.args = args self.kwargs = kwargs # 上面的几句话都仅仅是在给对象新增属性 return self.dispatch(request, *args, **kwargs) # dispatch返回什么 浏览器就会收到什么 # 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找 然后从产生对象的类里面找 最后类的父类依次往后 return view 通过源码发现url匹配关系可以变形成 url(r'^login/',views.view) # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址 2.当浏览器中输入login 会立刻触发view函数的运行 def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, # defer to the error handler. Also defer to the error handler if the # request method isn't on the approved list. # 我们先以GET为例 if request.method.lower() in self.http_method_names: # 判断当前请求方法是否在默认的八个方法内 # 反射获取我们自己写的类产生的对象的属性或者方法 # 以GET为例 handler = getattr(self,'get','取不到报错的信息') # handler = get(request) handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # 直接调用我们自己的写类里面的get方法 # 源码中先通过判断请求方式是否符合默认的八个请求方法 然后通过反射获取到自定义类中的对应的方法执行 django settings源码 前提: 1.django除了暴露给用户一个settings.py配置文件之外 自己内部还有一个全局的配置文件 2.我们在使用配置文件的时候 可以直接直接导入暴露给用户的settings.py也可以使用django全局的配置文件 并且后者居多 from django.conf import settings # django 用户全局配置文件 # from django.conf import global_settings res="day54.settings" import importlib data = importlib.import_module(res) print(data.name) 等于 from day54 import settings print(settings.name) 3.django的启动入口是manage.py import os import sys if __name__ == "__main__": # django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day54.settings") class Settings(object): def __init__(self, settings_module): # settings_module = 'day54.settings' # update this dict from global settings (but only for ALL_CAPS settings) for setting in dir(global_settings): # django全局配置文件 # dir获取django全局配置文件中所有的变量名 if setting.isupper(): # 判断文件中的变量名是否是大写 如果是大写才会执行/生效 setattr(self, setting, getattr(global_settings, setting)) # 给settings对象设置键值对 # 给settings对象设置键值对 settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值 # store the settings module in case someone later cares self.SETTINGS_MODULE = settings_module # 'day54.settings' mod = importlib.import_module(self.SETTINGS_MODULE) # mod = 模块settings(暴露给用户的配置文件) for setting in dir(mod): # for循环获取暴露给用户的配置文件中所有的变量名 if setting.isupper(): # 判断变量名是否是大写 setting_value = getattr(mod, setting) # 获取大写的变量名所对应的值 setattr(self, setting, setting_value) # 给settings对象设置键值对 """ d = {} d['username'] = 'jason' d['username'] = 'egon' 用户如果配置了就用用户的 用户如果没有配置就用系统默认的 其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的 """ class LazySettings(LazyObject): def _setup(self, name=None): # os.environ你可以把它看成是一个全局的大字典 settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings # settings_module = 'day54.settings' self._wrapped = Settings(settings_module) # Settings('day54.settings') settings = LazySettings() # 单例模式 作业: 参考django settings源码 实现自己的项目也能够做到 用户配置了就用用户的 用户没有配置 就用全局的 模板层 模板语法 两大类 {{}} 变量相关 {%%} 逻辑相关 为模板传值 过滤器: | 前后端取消转义: 前端: |safe 后端: from django.utils.safestring import mark_safe zzz = mark_safe('<h1>阿萨德搜啊第三款垃圾袋</h1>') |safe |filesizeformat |date 标签: {%%} {#{% for foo in l %}#} {# <p>{{ forloop }}</p>#} {#{% endfor %}#} {##} {##} {#{% if '' %}#} {#<p>xxx条件为true</p>#} {# {% else %}#} {# <p>xxx条件为false</p>#} {#{% endif %}#} {##} {#{% for foo in '' %}#} {# {% if forloop.first %}#} {# <p>这是我的第一次</p>#} {# {% elif forloop.last %}#} {# <p>这是最后一次了啊</p>#} {# {% else %}#} {# <p>来啊来啊!!!</p>#} {# {% endif %}#} {# {% empty %}#} {# <p>当for循环的对象为空的时候 会走empty</p>#} {#{% endfor %}#} {##} {#<p>#} {# django模板语法在取值的时候 统一使用句点符(大白话就是 点号 .)#} {# {% with l.6.3.name as ttt %} 可以给一个比较复杂的取值操作取一个别名 之后在with语句中 就可以使用该别名#} {# {{ ttt }}#} {# {{ l.6.3.name }}#} {# {% endwith %}#} {#</p>#} {% for foo in d.keys %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.values %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.items %} <p>{{ foo }}</p> {% endfor %} for循环里面的forloop对象 if判断 自定义标签 过滤器 inclusion_tag 自定义固定的三步走战略: 1.必须在你的应用下新建一个名为templatetags文件夹 2.在该文件夹内新建一个任意名称的py文件 3.在该py文件中固定先写下面两句代码 from django import template register = template.Library() from django import template register = template.Library() # 自定义过滤器 @register.filter(name='baby') def index(a,b): # 该过滤器只做一个加法运算 是|add建议版本 """ |length |add |default |filesizeformat |truncatewords |truncatechars |safe |slice :param a: :param b: :return: """ print('下午刚起床 一脸懵逼') return a + b # 自定义标签 # 支持传多个值 @register.simple_tag(name='jason') def xxx(a,b,c,year): return '%s?%s|%s{%s'%(a,b,c,year) # 自定义inclusion_tag """ 接收用户传入的参数 然后作用于一个html页面 在该页面上渲染数据 之后将渲染好的页面 放到用户调用inclusion_tag的地方 """ # 自定义inclusion_tag @register.inclusion_tag('bigplus.html') def bigplus(n): l = [] for i in range(n): l.append('第%s项'%i) return {'l':l} 模板的继承 当多个页面整体的样式都大差不差的情况下 可以设置一个模板文件 在该模板文件中 使用block块划分多个预期 之后子版在使用模板的时候 可以通过block块的名字 来选定到底需要修改哪一部分区域 模板一般情况下 应该至少有三个可以被修改的区域 {% block css %} 子页面自己的css代码 {% endblock %} {% block content %} 子页面自己的html代码 {% endblock %} {% block js %} 子页面自己的js代码 {% endblock %} # 模板的继承 使用方式 {% extends 'home.html' %} {% block css %} <style> h1 { color: red; } </style> {% endblock %} {% block content %} <h1>登陆页面</h1> <form action=""> <p>username:<input type="text" class="form-control"></p> <p>password:<input type="text" class="form-control"></p> <input type="submit" class="btn btn-danger"> </form> {% endblock %} {% block js %} {% endblock %} # 一般情况下 模板上的block越多 页面的可扩展性就越强 模板的导入 {% include 'beautiful.html' %} 当你写了一个特别好看的form表单/列表标签等 可以将它当成一个模块 哪个地方需要 就直接导入使用即可 作业: 1.图书管理系统尝试着使用模板的继承来写 2.自己总结 必知必会13条 返回的结果哪些是querySet对象 1.单表操作 create_time = models.DateField() 关键性的参数 1.auto_now:每次操作数据 都会自动刷新当前操作的时间 2.auto_now_add:在创建数据的时候 会自动将创建时间记录下来 后续的修改不会影响该字段 在django中 你可以写一个单独测试某一个py文件的测试脚本 不需要再频繁的走web请求 模型层的单表操作 增删改查(已经讲过的) 神奇的双下滑查询(这个是没有讲过的 5分钟左右即可) 视图层 欠的FBV与CBV django settings源码 forms组件源码 django admin源码
templates
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<h1>我是一个特别特别的好看的form表单</h1>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<ul> {% for foo in l %} <li>{{ foo }}</li> {% endfor %} </ul>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板的继承</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css'%}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> {% block css %} {% endblock %} </head> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Brand</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> <li role="separator" class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> <form class="navbar-form navbar-left"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> <div class="container-fluid"> <div class="row"> <div class="col-md-2"> <div class="list-group"> <a href="/loginn/" class="list-group-item active"> 登陆 </a> <a href="/register/" class="list-group-item">注册</a> <a href="/home/" class="list-group-item">主页</a> </div> </div> <div class="col-md-10"> {#这是模板语法的注释 不会展示到前端#} {# 在你想把某一个页面作为模板的时候 可以在该页面上使用block划分区域 并且给该区域命名#} {# 之后你在使用该模板的时候 就可以通过名字 来指定需要修改哪一个区域的内容#} {% block content %} <div class="jumbotron"> <h1>Hello, world!</h1> <p>...</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p> </div> {% endblock %} </div> </div> </div> {% block js %} {% endblock %} </body> </html>
模板的继承
{#这是模板语法的注释 不会展示到前端#}
{# 在你想把某一个页面作为模板的时候 可以在该页面上使用block划分区域 并且给该区域命名#}
{# 之后你在使用该模板的时候 就可以通过名字 来指定需要修改哪一个区域的内容#}
{% block js %}
{% endblock %}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> </head> <body> <form action="" method="post"> username: <input type="text" name="username"> <input type="submit"> </form> {% load mytag %} {% bigplus 20 %} </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{% extends 'home.html' %} {% block css %} <style> h1 { color:red; } </style> {% endblock %} {% block content %} {% include 'beautiful.html' %} <h1>登录页面</h1> <form action=""> <p>username:<input type="text" class="form-control"></p> <p>password:<input type="text" class="form-control"></p> <input type="submit" class="btn btn-danger"> </form> {% endblock %} {% block js %} {% endblock %}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> </head> <body> {#<p>{{ n }}</p>#} {#<p>{{ ss }}</p>#} {#<p>{{ f }}</p>#} {#<p>{{ s }}</p>#} {#<p>{{ l }}</p>#} {#<p>{{ d }}</p>#} {#<p>{{ t }}</p>#} {#<p>{{ se }}</p>#} {#<p>传函数名,会自动加括号调用该函数,前端展示的是函数调用之后的返回值{{ index }}注意:如果函数需要参数,name不好意思,模板语法不支持</p>#} {#<p>{{ obj }}</p>#} {#<p>{{ obj.get_self }}</p>#} {#<p>{{ obj.get_cls }}</p>#} {#<p>{{ obj.get_static }}</p>#} {#<p>总结:django语法不支持给函数传参</p>#} {#<br>#} {#<h1>模板语法之标签:内部原理(会将|前面的当做第一个参数传入标签中)</h1>#} {#<p>{{ l|length }}</p>#} {#<p>{{ n|length }}</p>#} {#<p>{{ ss|default:'当|左边的变量为空就会返回|右边的值' }} default 跟你后端get方法很像</p>#} {#<p>{{ ss|default :'' }} default 必须要有两个参数</p>#} {##} {#<p>{{ file_size|filesizeformat }}</p>#} {#<p>{{ info|truncatewords:3 }} 就是按空格截取 三个点不算</p>#} {#<p>{{ info1|truncatewords:3 }}</p>#} {#<p>{{ info|truncatechars:6 }} 按字符截取内容,三个点也算</p>#} {#<p>{{ xxx|safe }}</p>#} {#<p>{{ yyy|safe }}</p>#} {#<p>{{ zzz }}</p>#} {#<p>{{ ctime }}</p>#} {#<p>{{ ctime|date:'Y-m-d' }} 只需要掌握年月日就可以了</p>#} {#<p>{{ n|add:100 }}</p>#} {#<p>{{ s|add:'hhhh 笑死大野狼' }}</p>#} {#<p>{{ l|slice:'0:3' }}</p>#} {#<p>{{ l|slice:'0:5:2' }}</p>#} {#<br>#} {#<h1>模板语法(逻辑相关)</h1>#} {#{% for foo in l %}#} {# <p>{{ forloop }}</p>#} {#{% endfor %}#} {##} {#{% if '' %}#} {# <p>xxx条件为True</p>#} {#{% else %}#} {# <p>xxx条件为false</p>#} {#{% endif %}#} {##} {#{% for foo in '' %}#} {# {% if forloop.first %}#} {# <p>这是我的第一次</p>#} {# {% elif forloop.last %}#} {# <p>这是我的最后一次</p>#} {# {% else %}#} {# <p>来啦来啦!!!</p>#} {# {% endif %}#} {# {% empty %}#} {# <p>当循环对象为空时会走empty</p>#} {##} {#{% endfor %}#} {#<p>django模板语法在取值的时候,统一用句点符(大白话就是 点号 .)</p>#} {#{% with l.6.3.name as tt %}#} {# <p>可以给一个比较复杂的取值操作取一个别名 之后在with语句中 就可以使用该别名</p>#} {# {{ tt }}#} {# {{ l.6.3.name }}#} {#{% endwith %}#} {##} {#{% for foo in d.keys %}#} {# <p>{{ foo }}</p>#} {#{% endfor %}#} {#{% for foo in d.values %}#} {# <p>{{ foo }}</p>#} {#{% endfor %}#} {#{% for foo in d.items %}#} {# <p>{{ foo }}</p>#} {#{% endfor %}#} <h1>自定义过滤器的使用</h1> <p>自定义过滤器 只能由两个形参</p> <p>但是你可以在给第二个参数传值的时候 传一个字符串</p> {% load mytag %} {{ 123|baby:1}} {#<p>{{ 123|baby:'1|2|3|4|5' }}</p>#} <h1>自定义标签 {#支持传多个参数 参数与参数之间 空格隔开即可#} {#</h1>#} {##} {#{% load mytag %}#} {#{% jason 1 2 3 year=2 %}#} <h1>自定义inclusion_tag 当你的页面上有一部分html代码需要经常被各个地方使用 并且需要传参才能渲染出来 那么你可以把该html代码部分制作成一个inclusion_tag 任何页面都能使用 </h1> {#{% load mytag %}#} {% bigplus 5 %} {##} {#<br>#} {% bigplus 10 %} </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{% extends 'home.html' %} {# 将home页面继承过来#} {% block css %} <style> h1 { color:blue; } </style> {% endblock %} {% block content %} <h1>注册页面</h1> {{ block.super }} {% include 'beautiful.html' %} <form action=""> <p>username:<input type="text" class="form-control"></p> <p>password:<input type="text" class="form-control"></p> <input type="submit" class="btn btn-danger"> </form> {% endblock %}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
""" Django settings for untitled project. Generated by 'django-admin startproject' using Django 1.11.11. For more information on this file, see https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.11/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'lq7n4bbqie*2==e)r2=vkxif!z^_v-%lpv^mkl%of^!8c%-j!4' # 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', 'app01.apps.App01Config', ] 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 = 'untitled.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , '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 = 'untitled.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/1.11/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/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ] # APPEND_SLASH = False # append_slash = False # 小写的没有效果 为什么? LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
"""untitled URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), url(r'^login/',views.MyLogin.as_view()), # url(r'^login/',views.view) FBV和CBV在路由匹配上是一致的,都是url+函数的内存地址 url(r'^reg/',views.reg), url(r'^home/',views.home), url(r'^loginn/',views.loginn), url(r'^register/',views.register) ]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render,HttpResponse # Create your views here. from django.template import Template,Context # FBV def index(request): temp = Template('<h1>{{ user }}</h1>') con = Context({"user":{"name":'jason',"password":'123'}}) res = temp.render(con) print(res) return HttpResponse(res) # CBV from django.views import View from django.conf import settings # django 用户全局配置文件 # from django.conf import global_settings class MyLogin(View): def get(self,request): print("from MyLogin get方法") return render(request,'login.html') def post(self,request): return HttpResponse('from MyLogin post方法') def reg(request): # 先验证是否Python所有的数据类型都可以被传递到前端 n = 0 ss = '' f = 1.11 s = '你大爷' l = [1,2,3,4,[1,2,3,4,{"name":"华盛顿"}]] d = {"name":"jason",'password':123} t = (1,2,3,4,5) se = {1,2,4,5,5} file_size = 1234344434 info = "my name is Joon and my age is 18" info1 = '撒娇发法师打发士大夫是发达懂法守法' def index(xxx): print(xxx) print('index') return '我是index函数的返回值' class Demo(object): def get_self(self): return '绑定给对象的方法' @classmethod def get_cls(cls): return '绑定给类的方法' @staticmethod def get_static(): return "我是静态方法,其实就是函数" obj = Demo() # 给模板传值的方式 # 方式1 # 通过字典的键值对的方式,指名道姓的一个个的传 # return render(request,'reg.html',{'n':n,'f':f}) # 方式2 # locals会将它所在的名称空间中的所有的名字全部传递给前端 # 该方法虽然好用 但是在某些情况下回造成资源的浪费 xxx = '<h1>波波棋牌室</h1>' yyy = '<script>alert(123)</script>' from django.utils.safestring import mark_safe zzz = mark_safe('<h1>阿萨德搜啊第三款垃圾袋</h1>') from datetime import datetime ctime = datetime.now() return render(request,'reg.html',locals()) # # 为了教学方便 我们以后就用locals() def home(request): return render(request,'home.html') def loginn(request): return render(request,'loginn.html') def register(request): return render(request,'register.html')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.test import TestCase # Create your tests here. # class Demo(object): # @classmethod # 绑定给类的 # @staticmethod # 静态方法,类和对象都行 # @property # 讲方法封装成属性 # pass
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) create_time = models.DateField() # 年月日 # create_time = models.DateTimeField() # 年月日时分秒 def __str__(self): return self.title
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django import template register = template.Library() # 自定义过滤器 @register.filter(name='baby') def index(a,b): # 该过滤器只做加减运算 是|add建议版本 """""" """ |length |add |default |filesizeformat |truncatewords |truncatechars |safe |slice """ print('下午一起床,很迷糊') return a + b # 自定义标签 # 支持传多个值 @register.simple_tag(name='jason') def xxx(a,b,c,year): return '%s?%s|%s{%s'%(a,b,c,year) # 自定义inclusion_tag @register.inclusion_tag('bigplus.html') def bigplus(n): l = [] for i in range(n): l.append(f'第{i}页') return {'l':l}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import os import sys if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "untitled.settings") import django django.setup() from app01 import models models.Book.objects.all() # 增 # 方式一:create # book_obj = models.Book.objects.create(title='三国演义', price=19.99, create_time='2021-7-28') # print(book_obj.title) # 方式二 :对象点 save()方法 from datetime import datetime # ctime = datetime.now() # book_obj = models.Book(title='西游记', price='12.44', create_time=ctime) # book_obj.save() # 查 # print(models.Book.objects.all()) # print(models.Book.objects.get(id=1)) # print(models.Book.objects.get(pk=1)) """ pk 会自动查找当前主键字段 """ # print(models.Book.objects.filter(pk=2)) # 改 # 1.update # models.Book.objects.filter(pk=3).update(title='红楼梦') # 2.对象 .save() # book_obj = models.Book.objects.get(pk=1) # book_obj.price = 666 # book_obj.save() # print(models.Book.objects.all()) # 删除 delete() # models.Book.objects.filter(pk=1).delete() # < 1 > all(): 查询所有结果 # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象) # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 # 只要pk不是1的数据全部查询出来 # print(models.Book.objects.exclude(pk=1)) # < 5 > order_by(*field): 对查询结果排序('-id') / ('price') # print(models.Book.objects.order_by('price')) # 默认是升序 # print(models.Book.objects.order_by('-price')) # 加负号就是降序 # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向 # print(models.Book.objects.order_by('price').reverse()) # < 7 > count(): 返回数据库中匹配查询(QuerySet) # print(models.Book.objects.count()) # 对查询出来的结果进行一个计数 # 的对象数量。 # < 8 > first(): 返回第一条记录 # print(models.Book.objects.filter(pk=1).first()) # < 9 > last(): 返回最后一条记录 # print(models.Book.objects.all().last()) # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False # print(models.Book.objects.filter(pk=20).exists()) # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 # model的实例化对象,而是一个可迭代的字典序列 # print(models.Book.objects.values('title', 'price')) # 得到的结果是列表套字典 # < 12 > values_list(*field): 它与values() # print(models.Book.objects.values_list('title', 'price')) # 得到的结果是列表套元组 # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列 # < 13 > distinct(): 从返回结果中剔除重复纪录 """ 去重的前提是 一定要有完全重复的数据 才能去重 """ # print(models.Book.objects.filter(title='西游记').distinct()) # print(models.Book.objects.values('title', 'price', 'create_time').distinct()) # 神奇的双下划綫 # 价格大于19 # res = models.Book.objects.filter(price__gt=19) # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" > CAST('19' AS NUMERIC) LIMIT 21; args=(Decimal('19'),) numeric limit """ # 价格大于等于19 # res = models.Book.objects.filter(price__gte=19) # print(res) """ (0.010) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" >= CAST('19' AS NUMERIC) LIMIT 21; args=(Decimal('19'),) """ # 查询价格小于20 # res = models.Book.objects.filter(price__lt=20) # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" < CAST('20' AS NUMERIC) LIMIT 21; args=(Decimal('20'),) """ # 查询价格小于等于20 # res = models.Book.objects.filter(price__lte=20) # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" <= CAST('20' AS NUMERIC) LIMIT 21; args=(Decimal('20'),) """ # 查询价格要么等于19,要么等于12 要么等于33 # res = models.Book.objects.filter(price__in=[12,19,33]) # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" IN ('33', '19', '12') LIMIT 21; args=(Decimal('33'), Decimal('19'), Decimal('12')) """ #查询价格在12-19之间 # res = models.Book.objects.filter(price__range=(12,19)) # 两边都包含 # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."price" BETWEEN '12' AND '19' LIMIT 21; args=(Decimal('12'), Decimal('19')) """ # 查询包含p """ 原生sql语句查询,模糊匹配 like """ # res = models.Book.objects.filter(title__contains='p') # 仅仅只能拿小写 # res = models.Book.objects.filter(title__icontains='p') # 忽略大小写 # print(res) """ (0.010) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."title" LIKE '%p%' ESCAPE '\' LIMIT 21; args=('%p%',) """ # 查询书籍是以3开头 # res = models.Book.objects.filter(title__startswith='三') # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."title" LIKE '三%' ESCAPE '\' LIMIT 21; args=('三%',) """ # 查询出版日期是2017年的 # res = models.Book.objects.filter(create_time__year=2021) # res = models.Book.objects.filter(create_time__month=5) # print(res) """ (0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."create_time" FROM "app01_book" WHERE "app01_book"."create_time" BETWEEN '2021-01-01' AND '2021-12-31' LIMIT 21; args=('2021-01-01', '2021-12-31') between """