django
2017-10-27 14:16:04 191 举报
AI智能生成
django的思维导图
作者其他创作
大纲/内容
2.django的基础
1.视图(views)
1.介绍
创建一个项目myproject├── manage.py└── mysite ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py创建一个应用myapp├── __init__.py├── admin.py├── models.py├── tests.py└── views.py这里的views就是视图每一个视图都是一个函数
2.项目引入
3.定义是视图函数
4.关于返回值
1.HttpResponse
2.render
3.redirect
2.路由(urls)
2.两种发放方式
1.项目发放
2.项目转发应用发放
3.模板(templates)
如果说我们光知道视图和路由转发之前只能用HttpResponse返回给浏览器的话,那么模板就是我们商用上的给用户真正看到的界面在视图上用到的返回值render就是用来调用渲染的函数这里的模板语言我们会做一个大的分类进行详细讲解
4.django的views
1.http协议
1.web框架本质
# !/usr/bin/env python# -*- coding:utf-8 -*-# __Author__ Jianer import socket def handle_request(client): buf = client.recv(1024) client.send(\"HTTP/1.1 200 OK\\\\\") client.send(\
2.简介
HTTP(hypertext transport protocol),即超文本传输协议。这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。HTTP就是一个通信规则,通信规则规定了客户端发送给服务器的内容格式,也规定了服务器发送给客户端的内容格式。其实学习的就是这个两个格式!客户端发送给服务器的格式叫“请求协议”;服务器发送给客户端的格式叫“响应协议”。即HTTP基于请求/响应模式。HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。URL:统一资源定位符,就是一个网址:协议名://域名:端口/路径HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
3.http的请求流程
在接受一个Http请求之前的准备 启动一个支持WSGI网关协议的服务器监听端口等待外界的Http请求,比如Django自带的开发者服务器或者uWSGI服务器。服务器根据WSGI协议指定相应的Handler来处理Http请求,并且初始化该Handler,在Django框架中由框架自身负责实现这一个Handler。此时服务器已处于监听状态,可以接受外界的Http请求当一个http请求到达服务器的时候 服务器根据WSGI协议从Http请求中提取出必要的参数组成一个字典(environ)并传入Handler中进行处理。在Handler中对已经符合WSGI协议标准规定的http请求进行分析,比如加载Django提供的中间件,路由分配,调用路由匹配的视图等。返回一个可以被浏览器解析的符合Http协议的HttpResponse。
2.wsgi
3.简单的python框架
1.一个简单的前端模板
在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以一般将要返回给用户的HTML写在指定文件中,然后再返回。如下:<pre><code><!DOCTYPE html><html><head lang=\"en\"> <meta charset=\"UTF-8\"> <title></title></head><body> <h1>Index</h1></body></html>index.html</code></pre>
2.一个form页面
<pre><code><!DOCTYPE html><html><head lang=\"en\"> <meta charset=\"UTF-8\"> <title></title></head><body> <form> <input type=\"text\" /> <input type=\"text\" /> <input type=\"submit\" /> </form></body></html>login.html</code></pre>
3.继承
4.请求协议
2.get请求
3.post请求
数据不会出现在地址栏中数据的大小没有上限有请求体请求体中如果存在中文,会使用URL编码!<pre><code># 例如:username=%E5%BC%A0%E4%B8%89&password=123我们都知道Http协议中参数的传输是\"key=value\"这种简直对形式的,如果要传多个参数就需要用“&”符号对键值对进行分割。如\"?name1=value1&name2=value2\
4.两者区别
Referer请求头
Referer请求头是比较有用的一个请求头,它可以用来做统计工作,也可以用来做防盗链。统计工作:我公司网站在百度上做了广告,但不知道在百度上做广告对我们网站的访问量是否有影响,那么可以对每个请求中的Referer进行分析,如果Referer为百度的很多,那么说明用户都是通过百度找到我们公司网站的。防盗链:我公司网站上有一个下载链接,而其他网站盗链了这个地址,例如在我网站上的index.html页面中有一个链接,点击即可下载JDK7.0,但有某个人的微博中盗链了这个资源,它也有一个链接指向我们网站的JDK7.0,也就是说登录它的微博,点击链接就可以从我网站上下载JDK7.0,这导致我们网站的广告没有看,但下载的却是我网站的资源。这时可以使用Referer进行防盗链,在资源被下载之前,我们对Referer进行判断,如果请求来自本网站,那么允许下载,如果非本网站,先跳转到本网站看广告,然后再允许下载。Referer的应用
5.django的httprequest
1.path
请求页面的全路径,不包括域名—例如,“/music/bands/the_beatles/”
2.method
请求中使用的HTTP方法的字符串表示。全大写表示。例如:if request.method == 'GET': do_something()elif request.method == 'POST': do_something_else()
3.GET
包含所有HTTP GET参数的类字典对象。参见QueryDict文档。
4.POST
包含所有HTTP POST参数的类字典对象。参见QueryDict文档。服务器收到空的POST请求的情况也是有可能发生的。也就是说,表单form通过HTTP POST方法提交请求,但是表单中可以没有数据。不能使用语句if request.POST来判断是否使用HTTP POST方法;应该使用if request.method == 'POST' (参见本表的method属性)。注意:POST不包括file-upload信息。参见FILES属性。
5.COOKIES
包含所有cookies的标准python字典对象。Keys和values都是字符串。
6.FILES
包含所有上传文件的类字典对象。FILES中的每个Key都是<input type=\"file\" name=\"\"/>标签中name属性的值。FILES中的每个value同时也是一个标准Python字典对象,包含下面三个Keys:filename:上传文件名,用Python字符串表示content-type:上传文件的Content typecontent:上传文件的原始内容注意:只有在请求方法是POST,并且请求页面中<form>有enctype=\"multipart/form-data\"属性时FILES才拥有数据。否则,FILES是一个空字典。
7.META
包含所有可用HTTP头部信息的字典。例如:CONTENT_LENGTHCONTENT_TYPEQUERY_STRING:未解析的原始查询字符串REMOTE_ADDR:客户端IP地址REMOTE_HOST:客户端主机名SERVER_NAME:服务器主机名SERVER_PORT:服务器端口META中这些头加上前缀HTTP_最为Key,例如:HTTP_ACCEPT_ENCODINGHTTP_ACCEPT_LANGUAGEHTTP_HOST:客户发送的HTTP主机头信息HTTP_REFERER:referring页HTTP_USER_AGENT:客户端的user-agent字符串HTTP_X_BENDER:X-Bender头信息
8.user
是一个django.contrib.auth.models.User对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登录;if request.user.is_authenticated(): #Do something for logged-in users.else: #Do something for anonymous users.只有激活Django中的AuthenticationMiddleware时该属性才可用
9.session
唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用
10.raw_post_data
原始HTTP POST数据。未解析过。高级处理时会有用处。
11.body
更完整的request请求包,或者说完整的信息
6.django的httpresponse
5.views的FBV
1.urls的写法
2.views的写法
3.html的写法
<pre><code><!DOCTYPE html><html lang=\"en\"><head> <meta charset=\"UTF-8\"> <title>index</title></head><body> <form action=\"\" method=\"post\"> <input type=\"text\" name=\"A\" /> <input type=\"submit\" name=\"b\" value=\"提交\" /> </form></body></html></code></pre>
6.views的CBV
3.注意事项
类要继承 View ,类中函数名必须小写。一般只会用到post和get
6.django的urls
1.url的本质
1.视图与urls的映射
它的本质是 URL 模式以及要为该 URL 模式调用的视图函数之间的映射表。django-admin.py startproject 运行时,该脚本会自动为你建了一份 URLconf(URL configuration)(即 urls.py 文件)。由于它是纯Python代码(pure Python code),可以动态创建(Dynamically Constructed).
2.创建
3.循环匹配
当访问 URL /hello/ 时,Django根据 ROOT_URLCONF 的设置装URLconf 然后按顺序逐个匹配URLconf里的URLpatterns,直到找到一个匹配的。 当找到这个匹配 的URLpatterns就调用相关联的view函数,并把 HttpRequest 对象作为第一个参数。
4.进行web返回
视图函数必须返回一个HttpResponse,Django转换HttpResponse为一个适合的HTTP response, 以Web page显示出来
2.patterns函数
1.用法
2.传参用法
3.正则匹配传参
4.正则同时额外加参
5.额外覆盖正则
6.缺省视图
7.urls转发
3.include函数
1.功能
2.注意事项
1.不能包含$
include() 的正则表达式并不包含一个 $ (字符串结尾匹配符),但是包含了一个斜杆/。
2.排除匹配部分
3.匹配模式
1.不含变量参数
如在url输入框中输入 http://127.0.0.1:8000/blog/index/ 则,它会截取include()中匹配的url,这里是”blog” 接下来找到了宿主了也就是myblog.urls,那么剩余的部分 这里是”index” 去匹配myblog.urls中的url模式。
2.含有变量参数
3.复杂型
4.高级配置
1命名组
1.无命名
2.命名
3.常见匹配模式
8.django中的form
1.forms
1.由来
在Django社区上会经常看到django.newforms这个词语。当人们讨论django.newforms,其实就是我们本章里面介绍的django.forms。改名其实有历史原因的。 当Django一次向公众发行时,它有一个复杂难懂的表单系统:django.forms。后来它被完全重写了,新的版本改叫作:django.newforms,这样人们还可以通过名称,使用旧版本。 当Django 1.0发布时,旧版本django.forms就不再使用了,而django.newforms也终于可以名正言顺的叫做:django.forms。
2.功能
表单框架最主要的用法是,为每一个将要处理的HTML的`` <Form>`` 定义一个Form类。 这样我们就可以不用通过手动编写,来使用一个form表单了
3.实践
1.我们只需定义一个Form类。 这个类可以存在于任何地方,甚至直接写在`` views.py`` 文件里也行,但是社区的惯例是把Form类都放到一个文件中:forms.py。在存放`` views.py`` 的目录中,创建这个文件,然后输入
2.继承django的forms.Form
from django import forms class ContactForm(forms.Form): subject = forms.CharField() email = forms.EmailField(required=False) message = forms.CharField()
这看上去简单易懂,并且很像在模块中使用的语法。 表单中的每一个字段(域)作为Form类的属性,被展现成Field类。这里只用到CharField和EmailField类型。 每一个字段都默认是必填。要使email成为可选项,我们需要指定required=False。
3.用python解释器进行查看会发现,如果打印会产生一些html标签
1.默认情况下使用的label标签
2.使用ul标签
>>> print f.as_ul()<li><label for=\"id_subject\">Subject:</label> <input type=\"text\" name=\"subject\" id=\"id_subject\" /></li><li><label for=\"id_email\">Email:</label> <input type=\"text\" name=\"email\" id=\"id_email\" /></li><li><label for=\"id_message\">Message:</label> <input type=\"text\" name=\"message\" id=\"id_message\" /></li>
3.使用p标签
>>> print f.as_p()<p><label for=\"id_subject\">Subject:</label> <input type=\"text\" name=\"subject\" id=\"id_subject\" /></p><p><label for=\"id_email\">Email:</label> <input type=\"text\" name=\"email\" id=\"id_email\" /></p><p><label for=\"id_message\">Message:</label> <input type=\"text\" name=\"message\" id=\"id_message\" /></p>
4.只显示某一个字段
>>> print f['subject']<input type=\"text\" name=\"subject\" id=\"id_subject\" />>>> print f['message']<input type=\"text\" name=\"message\" id=\"id_message\" />
4.合法性
1.当你前端做一次提交,或者实例化form类时传入了参数,就相当于做了一次form对象的生成
2.合法性判断is_valid()
如果我们对于每一个参数都传值那么是合法的
2.required=False如果我们对于这样的字段不传值那么也是合法的
3.如果留空subject或message,整个Form就不再合法了:
3.error查看
1.逐一查看每个字段的出错消息
2.每一个对象都继承了errors方法
4.完全合法
如果一个Form实体的数据是合法的,它就会有一个可用的cleaned_data属性。 这是一个包含干净的提交数据的字典。 Django的form框架不但校验数据,它还会把它们转换成相应的Python字典类型数据,这叫做清理数据
5.注意事项
我们的contact form只涉及字符串类型,它们会被清理成Unicode对象。如果我们使用整数型或日期型,form框架会确保方法使用合适的Python整数型或datetime.date型对象。
5.设置规则
django的model可以制定很多需要的规则,比方说输入的字符数大于10等
name = models.CharField(max_length=64)
1.如果不填写那么报错
2.设置css样式
3.clean全局规则验证
def clean(self): if self.cleaned_data.get(\"password\") is not None: if self.cleaned_data.get(\"password\")==self.cleaned_data.get(\"reqeat_password\"): return self.cleaned_data else: raise ValidationError(\"抛出两次密码不一致错误\") else: return self.cleaned_data
4.某一项规则验证
def clean_password(self): if len(self.cleaned_data.get(\"password\"))>8: return self.cleaned_data.get(\"password\") else: raise ValidationError(\"密码长度不到8位\")
1.django源代码中规定,clean_func会在clean之前运行2.如果clean_func中验证不通过,那么这条数据会变成errors数据3.在出现errors数据后如果clean和clean_func调用了同样的一组数据,那么clean会报错,所以\t尽量使用get的方式取字典,不要用[]的形式
2.modelform
1.导入
from django import forms
3.储存数据
if obj.is_valid(): obj.save() # 创建数据
4.一对多和多对多
model例子
views中的操作
def index(request): if request.method == \"GET\
5.修改数据
1.解释
修改表数据是,记得把instance信息也传进去,不然是新建数据,而不是对某行数据进行修改。编辑用户信息,新url方式保留默认数据
2.urls
3.views
4.htmls
<body> <ul> {% for row in li %} <li>{{ row.username }} - {{ row.user_type.caption }} - <a href=\"/edit-{{ row.id }}/\">编辑</a></li> {% endfor %} </ul></body>
<body> <form method=\"POST\" action=\"/edit-{{ nid }}/\"> {% csrf_token %} {{ mf.as_p }} <input type=\"submit\" value=\"提交\" /> </form></body>
6.钩子
从上面的Form和ModelForm中,他们都是继承了BaseForm,而is_valid是在BaseForm中定义的,所以ModelForm也能和Form一样使用各种钩子
额外字段
class UserInfoModelForm(forms.ModelForm): is_rmb = fields.CharField(widget=widgets.CheckboxInput()) # 额外字段 class Meta: model = models.UserInfo fields = '__all__'
7.总结
1. 生成HTML标签:class Meta: ... 2. mf = xxxModelForm(instance=ModelObj) 生成默认值 3. 额外的标签, is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput()) 4. 各种验证 is_valid() -> 各种钩子... 5. mf.save() # 或 instance = mf.save(False) instance.save() mf.save_m2m()
10.补充二
1.ajax
2.laccess
3.分页
1.常用函数
2.html功能
<!DOCTYPE html><html lang=\"en\"><head> <meta charset=\"UTF-8\"> <title>Title</title> <script src=\"https://cdn.staticfile.org/jquery/3.2.1/jquery.js\"></script></head><body><div class=\"container\"> <div class=\"row\"> <ul> {% for i in booklist %}div yne-bulb-block=\"paragraph\
3.views功能
def showbook(request): booklist=Book.objects.all()div yne-bulb-block=\"paragraph\
4.文件上传
html要求
type='file'
<form action='/login/' method='post' enctype='multipart/form-data'>\t\t{%csrf_token%}\t\t<p><input type='file' name='fileobj'></p>
views要求
def login(request):\tif request.method=='POST':\t\tprint (\"is fileobj str\
django
1初识django
1.怎么才能学django
1. Django是 python 语言写的一个Web框架包,所以你得知道一些 Python 基础知识。
没有经验也没有关系,慢慢来就好了,你一定可以学会,Django 很简单!
2.特点
1.强大的数据库功能
用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句
2.自带的强大的后台功能(admin)
几行简单的代码就让你的网站拥有一个强大的后台,轻松管理你的内容!
3.优雅的网址(urls)
用正则匹配网址,传递到对应函数,随意定义,如你所想!
4.模板系统(templates)
强大,易扩展的模板系统,设计简易,代码,样式分开设计,更容易管理。
5.缓存系统(memcached)
与memcached或其它的缓存系统联用,更出色的表现,更快的加载速度。
6.国际性特别的强(默认utf-8)
完全支持多语言应用,允许你定义翻译的字符,轻松翻译成不同国家的语言
3.简介
4.开发环境
1.python(3.6)
2.django版本(1.11.x)
1.下载方式pip intall Django
2.判断是否下载成功
5.基本命令
1.创建项目
django-admin.py startproject name这里的name是项目的名字
2.创建应用
python manage.py startapp app_name注意不要出现于现有名称重合的问题
3.创建数据表(创建更改的文件)python manage.py makemigrations
4.生成数据库文件
python manage.py migrate
5.运行django服务器
python manage.py runserver默认8000默认127.0.0.1python manage.py runserver 0.0.0.0:8000手动输入ip和端口
6.命令删除数据库python manage.py flush
7.创建一个管理员
python manage.py createsuperuser这里创建管理员可以考虑不输入邮箱 回车跳过就剋了
8.修改密码
python manage.py changepassword username这里的username是已有的用户名
9.强大的shell命令终端python manage.py shell
10.数据库shell终端python manage.py dbshell
11.终端上输入 python manage.py 可以看到详细的列表
3.django模板
1.解决的问题
1,显然,任何页面的改动会牵扯到Python代码的改动网站的设计改动会比Python代码改动更频繁,所以如果我们将两者分离开会更方便
2,其次,写后台Python代码与设计HTML是不同的工作,更专业的Web开发应该将两者分开页面设计者和HTML/CSS程序员不应该编辑Python代码,他们应该与HTML打交道
3,程序员写Python代码同时页面设计者写HTML模板会更高效,而不是一个人等待另一个人编辑同样的文件因此,使用Django的模板系统分离设计和Python代码会更干净更易维护
2.介绍
Django模板是一个string文本,它用来分离一个文档的展现和数据模板定义了placeholder和表示多种逻辑的tags来规定文档如何展现通常模板用来输出HTML,但是Django模板也能生成其它基于文本的形式
3.简单举例
4.几种方法
1,用{{}}包围的是变量,如{{person_name}},这表示把给定变量的值插入,如何指定这些变量的值我们即将说明
2,用{%%}包围的是块标签,如{%if ordered_warranty%}块标签的含义很丰富,它告诉模板系统做一些事情在这个例子模板中包含两个块标签:for标签表现为一个简单的循环结构,让你按顺序遍历每条数据if标签则表现为逻辑的if语句在这里,上面的标签检查ordered_warranty变量的值是否为True如果是True,模板系统会显示{%if ordered_warranty%}和{%endif%}之间的内容否则,模板系统不会显示这些内容模板系统也支持{%else%}等其它逻辑语句
3,上面还有一个过滤器的例子,过滤器是改变变量显示的方式上面的例子中{{ship_date|date:\
5.使用模板系统
1,用模板代码创建一个Template对象Django也提供指定模板文件路径的方式创建Template对象
2,使用一些给定变量context调用Template对象的render()方法这将返回一个完全渲染的模板,它是一个string,其中所有的变量和块标签都会根据context得到值
6.系统出发的报错
系统触发TemplateSyntaxError异常可能出于以下情况:1,不合法的块标签2,合法块标签接受不合法的参数3,不合法的过滤器4,合法过滤器接受不合法的参数5,不合法的模板语法6,块标签没关
7.内置的标签
1.if/else
1.基础用法
{% if today_is_weekend %} <p>Welcome to the weekend!</p>{% else %} <p>Get back to work.</p>{% endif %}
2.and,not,or用法
{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:{% if athlete_list and coach_list %} Both athletes and coaches are available.{% endif %}{% if not athlete_list %} There are no athletes.{% endif %}{% if athlete_list or coach_list %} There are some athletes or some coaches.{% endif %}{% if not athlete_list or coach_list %} There are no athletes or there are some coaches.{% endif %}{% if athlete_list and not coach_list %} There are some athletes and absolutely no coaches.{% endif %}
3.嵌套的使用and,or
{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:{% if today_is_weekend %} <p>Welcome to the weekend!</p>{% else %} <p>Get back to work.</p>{% endif %}
4.多个逻辑交级
多次使用同一个逻辑符号是合法的:{% if athlete_list or coach_list or parent_list or teacher_list %}
5.没有elif标签
没有{% elif %}标签,使用嵌套的{% if %}标签可以做到同样的事情:{% if athlete_list %} <p>Here are the athletes: {{ athlete_list }}.</p> {% else %} <p>No athletes are available.</p> {% if coach_list %} <p>Here are the coaches: {{ coach_list }}.</p> {% endif %} {% endif %}
6.神奇的endif
鬼知道为啥要有确认使用{% endif %}来关闭{% if %}标签,否则Django触发TemplateSyntaxError
2.for
1.循环列表
例如,显示给定athlete_list变量来显示athlete列表:<ul>{% for athlete in athlete_list %} <li>{{ athlete.name }}</li>{% endfor %}</ul>
2.reversed反序循环列表
<pre><code>{% for athlete in athlete_list reversed %}...{% endfor %}{% for %}标签可以嵌套:{% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul>{% endfor %}</code></pre>
3.没有continue
系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值类似的,系统也不支持continue语句
4.内置forloop变量
1.forloop.counter
表示循环次数int型它从1开始计数,第一次循环设为1{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %}
2.forloop.counter0
代表从零计数
3.forloop.revcounter
表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1倒数
4.forloop.revcounter0
总数减一然后在倒数
5.forloop.first
forloop.first当第一次循环时值为True,在特别情况下很有用比如第一次要不要:{% for object in objects %} {% if forloop.first %}<li class=\"first\">{% else %}<li>{% endif %} {{ object }} </li>{% endfor %}
6.forloop.last
forloop.last当最后一次循环时值为True就是最后一个我要不要<pre><code>{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}</code></pre>
7.forloop.parentloop
这把不要自己的循环计数,我要父级循环的<pre><code>{% for country in countries %} <table> {% for city in country.city_list %} <tr> <td>Country #{{ forloop.parentloop.counter }} </td> <td>City #{{ forloop.counter }}</td> <td>{{ city }}</td> </tr> {% endfor %} </table>{% endfor %}</code></pre>
8.其他
富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它Django会在for标签的块中覆盖你定义的forloop变量的值在其他非循环的地方,你的forloop变量仍然可用我们建议模板变量不要使用forloop,如果你需要这样做来访问你自定义的forloop,你可以使用forloop.parentloop
3.ifequal/ifnotequal
1. ifequal
{% ifequal %}比较两个值,如果相等,则显示{% ifequal %}和{% endifequal %}之间的所有内容:{% ifequal user currentuser %} <h1>Welcome!</h1> {% endifequal %}
2.可以使用字符串
参数可以是硬编码的string,单引号和双引号均可,下面的代码是合法的:{% ifequal section 'sitenews' %} <h1>Site News</h1> {% endifequal %} {% ifequal section \"community\" %} <h1>Community</h1> {% endifequal %}
3.支持else
和{% if %}一样,{% ifequal %}标签支持{% else %}{% ifequal section 'sitenews' %} <h1>Site News</h1> {% else %} <h1>No News Here</h1> {% endifequal %}
4.也支持数字
其它的模板变量,strings,integers和小数都可以作为{% ifequal %}的参数:{% ifequal variable 1 %} {% ifequal variable 1.23 %} {% ifequal variable 'foo' %} {% ifequal variable \"foo\" %}
5.不支持其他
8.内置过滤器
1.例子
这将显示通过lower过滤器过滤后{{ name }}变量的值,它将文本转换成小写使用(|)管道来申请一个过滤器过滤器可以串成链,即一个过滤器的结果可以传向下一个下面是escape文本内容然后把换行转换成p标签的习惯用法:{{ my_text|escape|linebreaks }}
2.带参过滤器
有些过滤器需要参数,需要参数的过滤器的样子:{{ bio|truncatewords:\"30\" }} 这将显示bio标量的前30个字,过滤器参数一直使用双引号必须双引号
3.addslashed
在任何后斜线,单引号,双引号前添加一个后斜线当你把一些文本输出到一个JavaScript字符串时这会十分有用
4.date日期
根据一个格式化string参数来格式化date或datetime对象,例如:{{ pub_date|date:\
5.escape
避免给定的string里出现and符,引号,尖括号当你处理用户提交的数据和确认合法的XML和XHTML数据时这将很有用escape将作如下的一些转换:Converts & to &amp; Converts < to &lt; Converts > to &gt; Converts \"(双引号) to &quot; Converts '(单引号) to &#39;
6.length
返回值的长度,你可以在一个list或string上做此操作或者在任何知道怎样决定自己的长度的Python对象上做此操作(即有一个__len__()方法的对象)
9.template的思想
现在我们对于Django地模板系统有了一个感性的认识,下面我们将指出一些有意为之的限制和它工作的哲学不像其他Web程序组件,程序员对模板系统的意见非常不一致一个很有意思的事实:Python至少拥有数十个——如果没有上百个——的开源模板语言实现,而且看来每一个都是因为其创造者认为现有的模板不能满足他们的要求。(事实上,据说写一个自己的模板系统是已经成了Python开发者必经的仪式了。如果你还没有写过自己的模板系统,试试看吧,真是很有意思。)所以,Django的第一个哲学就是Django不强求你使用它的模板语言Django的目标是提供一个full-stack框架,提供所有必须的web开发模块进行高效开发很多时候,使用Django的模板系统很方便,但不强求你使用它下面的“在视图中使用模板”一节我们会看到在Django中使用另一套模板语言,它同样简单易用但我们仍强烈需要Django的模板语言的工作方式,模板系统深植于World Online和Django发明者的Web开发方式中,下面是其中一些哲学:1,业务逻辑应该和呈现逻辑分离模板系统应该只负责控制显示和显示相关的逻辑我们视模板为一种控制显示和显示相关逻辑的工具,仅此而已。模板系统的功能就止于此。基于这个原因,Django模板无法直接调用Python代码。在Django模板里,所有的程序设计活动都止于对标签的使用。虽然你可以自定义模板标签来做任意的事情,但Django自己的模板标签不允许执行Python代码。2,语法应该和HTML/XML解耦Django的模板系统采用非HTML格式,如普通的文本,有些其它的模板语言是基于XML的XML的格式容易输错,并且XML的模板解析速度也容易变得很慢而难以接受3,页面设计者被假定为熟悉HTML代码Django模板系统没有设计成可以在Dreamweaver等WYSISYG编辑器中显示良好这类编辑器有很多限制,Django希望模板作者直接编辑HTML时感到舒适4,页面设计者被假定为不是Python程序员模板系统的作者意识到大部分Web页面的模板是页面设计者写的而不是Python程序员写的他们不具备Python知识,但Django也允许模板用Python来写,它提供了一种直接编写Python代码来扩展模板系统的方法5,目标不是发明一种编程语言目标只是提供足够的编程功能,如分支和循环等决定呈现相关的逻辑用由于上述的设计哲学,Django模板系统产生如下限制:1,模板不能设置和改变变量的值可以通过自定义模板标签来达到这个目标(I参看第10章),但是内置Django模板标签不允许这样做2,模板不能调用原生Python代码但是也可以通过自定义标签来做这件事情
10.模板继承
定义子模板可以覆盖的“块”,让我们看看前面的例子,编辑a.html文件:<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"> <html lang=\"en\"> <head> <title>The current time</title> </head> <body> <h1>My helpful timestamp site</h1> <p>It is now {{ current_date }}.</p> <hr> <p>Thanks for visiting my site.</p> </body> </html>
2.block
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"> <html lang=\"en\"> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html> 我们把这个模板叫做base.html,它定义了我们用来在其它页面使用的基本HTML框架现在就是子模板覆盖的工作了,要么添加内容,要么不改变块的内容(如果你在照着例子做,把base.html保存到模板目录下)这里我们使用了{% block %}模板标签,它告诉模板引擎一个子模板可能覆盖模板的这部分内容
3.子模板引用
既然我们有了基本模板,下面我们来编辑a.html来使用它:{% extends \"base.html\" %} {% block title %}The current time{% endblock %} {% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}
4.解释
这样是不是更美观一些?每个模板只包含属于自己的代码,根本没有冗余如果你想做整个网站的改动,只需要更改base.html即可,其它的模板也会立即响应改动它是这样工作的:1,当你载入模板current_datetime.html,模板引擎发现{% extends %}标签,注意到这是一个子模板模板引擎马上载入父模板base.html2,模板引擎在base.html里发现了3个{% block %}标签,就用子模板的内容替换了这些块于是我们定义的{% block title %}和{% block content %}被使用注意,既然子模板没有定义footer块,那么模板系统直接使用父模板的值父模板里{% block %}标签的内容一直可以作为后援方案你可以使用任意等级的继承,使用继承的常用方式是按以下三个步骤:1,创建base.html模板来掌控你的网站的整体外观,它的内容很少改变2,为你的网站创建base_SECTION.html模板,例如,base_photos.html,base_forum.html这些模板继承base.html并且包括部分专有的风格和设计3,为每个类别的页面创建单独的模板,例如论坛页面护着照片图库页面这些模板继承相应的部分模板这个方法最大化了代码重用并且很容易向公用区域添加东西,例如部分专有的导航下面是一些关于模板继承的小提示:1,如果在模板里使用{% extends %}的话,这个标签必须在所有模板标签的最前面,否则模板继承不工作2,通常基本模板里的{% block %}越多越好,子模板不必定义所有的父block,钩子越多越好3,如果你在很多模板里复制代码,很可能你应该把这些代码移动到父模板里4,如果你需要得到父模板的块内容,{{ block.super }}变量可以帮你完成工作当你需要给父块添加内容而不是取代它的时候这就很有用5,不能在同一模板里定义多个同名的{% block %},因为块标签同时在两个地方工作,不仅仅在子模板中,而且在父模板中也填充内容,如果子模板有两个同名的标签,父模板将不能决定使用哪个块内容来使用6,你给{% extends %}传递的模板名同样会被get_template()使用,所以会加上TEMPLATE_DIRS设置7,大部分情况下,{% extends %}的参数是string,但是也可以是变量,如果知道运行时才知道父模板的名字,这可以帮助你做一些很cool的动态内容
5.django的生命周期
2.路由系统
1.路由规则
在Django的urls中我们可以根据一个URL对应一个函数名来定义路由规则
2.代码
3.中间件看
1.定义
中间件是一个、一个的管道,如果相对任何所有的通过Django的请求进行管理都需要自定义中间件 中间件可以对进来的请求和出去的请求进行控制 中间件是一类。
2.django的代码演示
4.自定义中间件
1.代码展示
2.使用中间件
3.演示urls
4.演示views
def index(request): print 'This app01 Views.index' return HttpResponse('OK')
5.结果展示
'''Testmiddle process_requestNextmiddle process_requestTestmiddle process_viewNextmiddle process_viewThis app01 Views.indexNextmiddle process_responseTestmiddle process_response'''
6.结果解释
从输出结果可以看出:他是先执行Testmiddle 的request 方法又执行了Nextmiddle的 process_request方法。。。。
7.原理
当请求进来了到达中间件去settings里面找到MIDDLEWARE_CLASSES,MIDDLEWARE_CLASSES是一个元组有4个列表:process_request_lsit = []process_view_list = []process_response_list = []然后他循环MIDDLEWARE_CLASSES这个类:for 类 in MIDDLEWARE_CLASSES: obj = 类() if obj里有process_request方法: process_request_lsit.append(obj.process_request)然后运行for i in process_request_list: i() #加括号执行方法for i in process_view_list: i() ............
8.源码展示
def load_middleware(self): \"\"\" Populate middleware lists from settings.MIDDLEWARE_CLASSES. Must be called after the environment is fixed (see __call__ in subclasses). \"\"\
5.中间件流程梳理
1.为什么response没有返回值
首先看下自定义的中间件中的process_response方法他是有返回值的其他的是没有返回值的。这个return response是什么呢?
2.解答
3.如果又返回值
4.如果在request和views有返回
5.process_exception的触发机制
6.django的缓存机制
1.settings的配置
2.如何引用的
7.Session&Cookie
2.流程
3.结构
4.操作
2.解释
这里需要注意在session中,我们可以设置多个key:value的值,方便我们做很多事情,比如判断哪个用户: 如果用户登录后,那么他肯定有一个cookie那么他在访问购物车的时候,怎么判断是哪个用户呢?我们可以在session设置,当用户登录的时候,我们把的用户名,增加到session中,那么用户携带cookie访问的时候,我们就能判断是哪个一用来访问的!
3.对应关系
5.好处
使用Session和Cookie的好处:Cookie可以理解为一个身份证ID,你只能拿着他去和Server端进行通信,如果你没有这个ID那么server端也不知道你是谁!我在做Cookie和Session的实验,把Cookie删掉了!当我保存的时候直接给我提出来了,为什么呢?就是因为,server端不知道我是谁了,我已经没有密钥了。所以,只要Session和Cookie任意一方失效,就可以理解为:Cookie失效就相当于身份证ID过期,需要重新认证才可以继续使用。Session失效就相当于银行里的数据标识此ID无效,也需要重新申请。
7.django的orm
1.简介
2.怎么学习
1.理解
2.models
3 .url的配置
4.views的配置
5.插入测试数据
6.orm方式插入数据
7.通过对象进行添加
8.注意事项
3.orm的一对多
2.查找
1.正向查找
2.反向查找
1.实例
子主题
3.总结
4.多对多
2.初始化
1.models
2.查看
3.添加数据
1.正向添加
2.反向添加
3.自定义多对多第三章表
1.初始化
2.手动输入第三章表
4.自动创建和手动输入对比
5.查询
1.方法一
‘第一种方式都是基于表中的对象去找到第三张表! 通过间接的方式找到这张表的句柄!#正向查admin_obj = models.HostAdmin.objects.get(id=1)admin_obj.host.all()#反相差host_obj = models.Host.objects.get(id=1)host_obj.hostadmin_set.all()
2.方法二
用第二种方法就没有正向和反向这么一说了,直接查即可!relation_list = models.HostRelation.objects.all()for item in relation_list: #每一个item就是一个关系 print (item.user.username) print( item.host.hostname)relation_list = models.HostRelation.objects.filter(user__username='mosson') for item in relation_list: #每一个item就是一个关系 print( item.user.username) print (item.host.hostname)
3.对比
第一种方式只能找到某一个人管理的机器,不能把有的对应关系找到!
5.select_related的作用
select_related的作用,他就是用来优化查询的,没有他也可以,用它主要是用来优化ForeignKey
def index(request): ret = models.UserInfo.objects.all() #咱们看下他执行的什么SQL语句 print( ret.query)'''SELECT \"app01_userinfo\".\"id\
带有select_related的样子
def user_info(request): ret = models.UserInfo.objects.all().select_related() #咱们看下他执行的什么SQL语句 print ret.query SELECT \"app01_userinfo\".\"id\
如果我们带有了select_related()那么我们就可以在第一次查询的时候直接查询好相关联的第三正表的信息算是一种优化手段,一种减少sql的手段
6.链表操作梳理
1.一对多的创建
1、创建数据 \t通过对象创建 \t或者通过对象字段_id创建
查找 正向查找 \t 在通过filter的时候跨表使用 双下划线 '__' \t在获取值得时候通过.跨表 反向查找 \tDjango自动生成 表名_set \t其他操作和正向查找一样
3.多对多
自动生成关系表 间接的方式获取关系表,如果是正向的:一行数据的对象.ManyToMany字典就行 反向:一行数据的对象.表名_set
4.select_related
用于优化查询,一次性将查询的表和ForiegnKey关联的表一次性加载到内存。
7.Django中的F和Q
1.F查询
用来批量修改数据(使用查询条件的值)
例子
demo:比如我有个price这个列,我想让price自增10或者某一些自增10# from django.db.models import F# models.Tb1.objects.update(num=F('num')+10)
2.Q查询
用来做条件查询的
有没有这么一种情况:username=mosson或 username=wusir 或 username=alex 并且 age=18的需求?原生的查询是不支持的!所以就用到了Q~
第一步:#生成一个搜索对象search_q = Q() #在生成两个搜索对象search1 = Q()search2 = Q()
第四步:#执行搜索models.HostInfo.objects.filter(search_q)
8.分组和聚合查询
通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。
可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
查询alex出的书总价格
查询各个出版社最便宜的书价是多少
9.双下划线__
1.下划线单表查询
2.下划线多表查询
# ret3=models.Book.objects.filter(title='Python').values('id')# print(ret3)#[{'id': 1}] #正向查找(条件)之一对多 ret4=models.Book.objects.filter(title='Python').values('publisher__city') print(ret4) #[{'publisher__city': '北京'}] #正向查找(条件)之多对多 ret5=models.Book.objects.filter(title='Python').values('author__name') print(ret5) ret6=models.Book.objects.filter(author__name=\"alex\
10.改update和save
实例
注意项
2.update
#---------------- update方法直接设定对应属性---------------- models.Book.objects.filter(id=3).update(title=\"PHP\") ##sql: ##UPDATE \"app01_book\" SET \"title\" = 'PHP' WHERE \"app01_book\".\"id\
3.save
4.补充
此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。
11.在django查看sql命令
注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:
12.都是基于搜索的删除
我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除。
13.关于orm和SQLAlchemy的看法
Django 的 Model 驱动对数据库层面上的实现细节关注的非常少,开发者定义模型的过程非常接近声明式而非过程式,对于新项目来说,可能是这个原因让 Django Model 比 SQLAlchemy 讨人喜欢。传统的 SQLAlchemy 的使用方法是不入侵模型,在单独的地方定义表结构、映射规则,然后用 SQLAlchemy 驱动注入到模型类里去,这种方法可以完全避免模型与数据库的耦合,但是定义繁琐,要求开发者完全明白 engine、metadata、table、column、mapper 等概念,如果没有读过《企业应用架构模式》一类书籍会被弄得很乱。现在 SQLAlchemy 提供了 declarative 的方式,和 Django Model 很像,但是和声明式模型还是有一定的距离,好在对于灵活性几乎没损失。但是我对比了一下 Django Model 和 SQLAlchemy declarative,发现 Django Model 还是更简洁一些。例如对于类关联,Django 只要直接声明外键,就自动产生关联对象,而 SQLAlcyhemy 要定义外键、relationship 对象,如果有多个外键还要自己指定 join 规则…… 总之灵活性是好东西,但是不是什么情况下都讨人喜欢的。我本来想说这个是 ActiveRecord style 和 Data Mapper style 区别导致的,但是细想了一下,Django Model 并不是简单的 ActiveRecord,其对于复杂关联甚至继承的映射都有很好的适应性,应该和 SQLAlchemy 的 declarative 是同类型的,是对 Data Mapper 的 Active Record style 包装。
因为在Django世界中它的ORM就是事实标准。Django最重要的特色是什么?从ORM快速生成后台管理界面!另外还有ModelForm、数据迁移(migration)等等从Django ORM延伸出去的概念……如果你选用了SQLAlchemy,那么这一切都没有了,你必须自行搭建,或者选用第三方库。话说,没有了内置ORM、没有了内置后台管理界面、没有了内置ModelForm、没有了数据迁移的Django,还是Django吗?不如直接用其它更轻量或更松散的框架好了!另外,在Django之外单独使用Django ORM是不靠谱的。如果是其它环境,使用SQLAlchemy就好了。
9.杂项补充
1.序列化
关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。
2.第一种方式
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize(\"json\
3.json.dumps
import json #ret = models.BookType.objects.all().values('caption')ret = models.BookType.objects.all().values_list('caption') ret=list(ret) result = json.dumps(ret)
4.json处理date
由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展
2.内置信号量
1常用的信号量
2.导入方式
3.使用方法
3.自定义信号量
import django.dispatchpizza_done = django.dispatch.Signal(providing_args=[\"toppings\
2.注册
3.触发
4.由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发
0 条评论
回复 删除
下一页