Django 基础篇
Django 基础篇
一、什么是框架?
框架呢就是指:为解决一个开放性问题而设计的具有一定约束性的支撑结构。对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
二、自定义web框架
通过python标准库提供的wsgiref模块开发一个自己的Web框架。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server def index(): return 'index' def login(): return 'login' def routers(): urlpatterns = ( ('/index/',index), ('/login/',login), ) return urlpatterns def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] urlpatterns = routers() func = None for item in urlpatterns: if item[0] == url: func = item[1] break if func: return func() else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8000, RunServer) print "Serving HTTP on port 8000..." httpd.serve_forever()
三、MTV和MVC模式
1.MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。
2..Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
3.让我们用图来看一下完整的web请求执行的过程:
四、Django基础知识:
4.1 创建Django项目过程中常用的一些命令:
1、终端:django-admin startproject sitename(创建一个项目)
2、 python manage.py runserver 0.0.0.0 (启动一个应用程序)
python manage.py startapp appname (创建一个应用程序)
python manage.py syncdb
python manage.py makemigrations (创建数据库表单)
python manage.py migrate(创建数据库)
python manage.py fiush (清空数据库)
4.2Django项目的配置文:
4.2.1 数据库文件配置:
1 1 django默认支持sqlite,mysql, oracle,postgresql数据库。 2 3 <1> sqlite 4 5 django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3 6 7 <2> mysql 8 9 引擎名称:django.db.backends.mysql 10 11 2 mysql驱动程序 12 13 MySQLdb(mysql python) 14 mysqlclient 15 MySQL 16 PyMySQL(纯python的mysql驱动程序) 17 18 3.DATABASES = { 19 20 'default': { 21 22 'ENGINE': 'django.db.backends.mysql', 23 24 'NAME': 'books', #你的数据库名称 25 26 'USER': 'root', #你的数据库用户名 27 28 'PASSWORD': '', #你的数据库密码 29 30 'HOST': '', #你的数据库主机,留空默认为localhost 31 32 'PORT': '3306', #你的数据库端口 33 34 } 35 36 } 37 38 39 4.NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建 40 41 USER和PASSWORD分别是数据库的用户名和密码。 42 43 设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。 44 45 然后,启动项目,会报错:no module named MySQLdb 46 47 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL 48 49 所以,我们只需要找到项目名文件下的__init__,在里面写入: 50 51 import pymysql 52 pymysql.install_as_MySQLdb()
4.2.2 模板和静态文件的简单配置:
TEMPLATE_DIRS = ( os.path.join(BASE_DIR,'templates'), ) STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # 建立文件夹名称和在html文件中引用js等都用这个名字。保持三者一致
4.2.3其余文件配置详解:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
一、概述: #静态文件交由Web服务器处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例): # URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx. #conf里的location |---------->如果是静态文件,则由nginx直接处理 |---------->如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配 # 以上是部署到Web服务器后的处理方式,为了便于开发,Django提供了在开发环境的对静态文件的处理机制,方法是这样: #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles', #2、在urls.py里面加入 if settings.DEBUG: urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }), url(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), ) # 3、这样就可以在开发阶段直接使用静态文件了。 二、MEDIA_ROOT和MEDIA_URL #而静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的: #MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件。如果你定义 #MEDIA_ROOT=c:\temp\media,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c:\temp\media\abc #eg: class blog(models.Model): Title=models.charField(max_length=64) Photo=models.ImageField(upload_to="photo") # 上传的图片就上传到c:\temp\media\photo,而在模板中要显示该文件,则在这样写 #在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写: BASE_DIR= os.path.abspath(os.path.dirname(__file__)) MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/') #MEDIA_URL是指从浏览器访问时的地址前缀,举个例子: MEDIA_ROOT=c:\temp\media\photo MEDIA_URL="/data/" #在开发阶段,media的处理由django处理: # 访问http://localhost/data/abc/a.png就是访问c:\temp\media\photo\abc\a.png # 在模板里面这样写<img src="{{MEDIA_URL}}abc/a.png"> # 在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置, # 以便能让web服务器能访问media文件 # 以nginx为例,可以在nginx.conf里面这样: location ~/media/{ root/temp/ break; } # 具体可以参考如何在nginx部署django的资料。 三、STATIC_ROOT和STATIC_URL、 STATIC主要指的是如css,js,images这样文件,在settings里面可以配置STATIC_ROOT和STATIC_URL, 配置方式与MEDIA_ROOT是一样的,但是要注意 #STATIC文件一般保存在以下位置: #1、STATIC_ROOT:在settings里面设置,一般用来放一些公共的js,css,images等。 #2、app的static文件夹,在每个app所在文夹均可以建立一个static文件夹,然后当运行collectstatic时, # Django会遍历INSTALL_APPS里面所有app的static文件夹,将里面所有的文件复制到STATIC_ROOT。因此, # 如果你要建立可复用的app,那么你要将该app所需要的静态文件放在static文件夹中。 # 也就是说一个项目引用了很多app,那么这个项目所需要的css,images等静态文件是分散在各个app的static文件的,比 # 较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT。 #3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。 # STATIC_URL的含义与MEDIA_URL类似。 # ---------------------------------------------------------------------------- #注意1: #为了后端的更改不会影响前端的引入,避免造成前端大量修改 STATIC_URL = '/static/' #引用名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"statics") #实际名 ,即实际文件夹的名字 ) #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找 #<script src="/statics/jquery-3.1.1.js"></script> #------error-----不能直接用,必须用STATIC_URL = '/static/': #<script src="/static/jquery-3.1.1.js"></script> #注意2(statics文件夹写在不同的app下,静态文件的调用): STATIC_URL = '/static/' STATICFILES_DIRS=( ('hello',os.path.join(BASE_DIR,"app01","statics")) , ) #<script src="/static/hello/jquery-1.8.2.min.js"></script> #注意3: STATIC_URL = '/static/' {% load staticfiles %} # <script src={% static "jquery-1.8.2.min.js" %}></script>
4.3 路由系统:
1、每个路由规则对应一个view中的函数:
url(r'^index/(\d*)', views.index), # 正则表达式中还有分组,这样可以把参数传递到后台的视图函数,有专门的接受参数的地方 url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage), # 对接受参数的参数名称进行了限制,必须为<>内的名字 url(r'^manage/(?P<name>\w*)', views.manage,{'id':333})
2、根据app对路由规则进行一次分类:
url(r'^web/',include('web.urls')),
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
4.4 模板
4.4.1、模版的执行
模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。
4.4.2、模板语言语法
模板中也有自己的语言,该语言可以实现数据展示
- {{ item }} # 变量存在的地方
- {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
forloop.counter
forloop.first
forloop.last - {% if ordered_warranty %} {% else %} {% endif %}
- 母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %} #要写在HTML的最头顶
{% block title %}{% endblock %} - 帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
通过simple_tag实现模版语言中的帮助方法
a、在app中创建templatetags文件夹
b、创建任意 .py 文件,如:xx.py
1 #!/usr/bin/env python 2 #coding:utf-8 3 4 from django import template 5 from django.utils.safestring import mark_safe 6 from django.template.base import resolve_variable, Node, TemplateSyntaxError 7 8 register = template.Library() 9 10 @register.simple_tag 11 def my_simple_time(v1,v2,v3): 12 return v1 + v2 + v3 13 14 @register.simple_tag 15 def my_input(id,arg): 16 result = "<input type='text' id='%s' class='%s' />" %(id,arg,) 17 return mark_safe(result)
c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xxx %}
d、使用simple_tag
{% my_simple_time 1 2 3%} {% my_input 'id_username' 'hide'%}
e、再settings中配置当前app,不然django无法找到自定义的simple_tag
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', )
4.5 视图函数
4.5.1
http请求中产生两个核心对象:
http请求:HttpRequest对象
http响应:HttpResponse对象
所在位置:django.http
之前我们用到的参数request就是HttpRequest 检测方法:isinstance(request,HttpRequest)
1 HttpRequest对象的属性和方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # path: 请求页面的全路径,不包括域名 2 # 3 # method: 请求中使用的HTTP方法的字符串表示。全大写表示。例如 4 # 5 # if req.method=="GET": 6 # 7 # do_something() 8 # 9 # elseif req.method=="POST": 10 # 11 # do_something_else() 12 # 13 # GET: 包含所有HTTP GET参数的类字典对象 14 # 15 # POST: 包含所有HTTP POST参数的类字典对象 16 # 17 # 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过 18 # HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用 19 # if req.POST来判断是否使用了HTTP POST 方法;应该使用 if req.method=="POST" 20 # 21 # 22 # 23 # COOKIES: 包含所有cookies的标准Python字典对象;keys和values都是字符串。 24 # 25 # FILES: 包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中 name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys: 26 # 27 # filename: 上传文件名,用字符串表示 28 # content_type: 上传文件的Content Type 29 # content: 上传文件的原始内容 30 # 31 # 32 # user: 是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前 33 # 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你 34 # 可以通过user的is_authenticated()方法来辨别用户是否登陆: 35 # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware 36 # 时该属性才可用 37 # 38 # session: 唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。 39 40 #方法 41 get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 42 req.path:/index33
注意一个常用方法:request.POST.getlist('')
2 HttpResponse对象:
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染: render()(推荐) render_to_response(), 页面跳转: redirect("路径") locals(): 可以直接将函数中所有的变量传给模板
注意:
总结: render和redirect的区别: 1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分 除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦. 2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后
又得重新登录.
4.6、Model(模型)
涉及到数据库相关的操作的时候一般会这样操作:
- 创建数据库,设计表结构和字段
- 使用 MySQLdb(pymysql) 来连接数据库,并编写数据访问层代码
- 业务逻辑层去调用数据访问层执行数据库操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
mport MySQLdb def GetList(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchall() db.close() return data def GetSingle(sql): db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') cursor = db.cursor() cursor.execute(sql) data = cursor.fetchone() db.close() return data
django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。
1、创建Model,之后可以根据Model来创建数据库表:
1 from django.db import models 2 3 class userinfo(models.Model): 4 name = models.CharField(max_length=30) 5 email = models.EmailField() 6 mode = models.TextField()
字段详解:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField 字符串字段 必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制<br>23、models.ImageField 图片<br>24、models.FilePathField 文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to
数据库中表与表之间的关系:
- 一对多,models.ForeignKey(ColorDic)
- 一对一,models.OneToOneField(OneModel)
- 多对多,authors = models.ManyToManyField(Author)
应用场景:
- 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。
例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。 - 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。 - 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。
例如:创建用户信息,需要为用户指定多个爱好。
2、数据库操作
- 增加:创建实例,并调用save
- 更新:a.获取实例,再sava;b.update(指定列)
- 删除:a. filter().delete(); b.all().delete()
- 获取:a. 单个=get(id=1) ;b. 所有 = all()
- 过滤:filter(name='xxx');filter(name__contains='');(id__in = [1,2,3]) ;
icontains(大小写无关的LIKE),startswith和endswith, 还有range(SQLBETWEEN查询)'gt', 'in', 'isnull', 'endswith', 'contains', 'lt', 'startswith', 'iendswith', 'icontains','range', 'istartswith' - 排序:order_by("name") =asc ;order_by("-name")=desc
- 返回第n-m条:第n条[0];前两条[0:2]
- 指定映射:values
- 数量:count()
- 聚合:from django.db.models import Min,Max,Sum objects.all().aggregate(Max('guest_id'))
- 原始SQL
cursor = connection.cursor() cursor.execute('''SELECT DISTINCT first_name ROM people_person WHERE last_name = %s""", ['Lennon']) row = cursor.fetchone()
4.7.Form
django中的Form一般有两种功能:
- 输入html
- 验证用户输入
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/usr/bin/env python # -*- coding:utf-8 -*- import re from django import forms from django.core.exceptions import ValidationError def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class PublishForm(forms.Form): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'), ) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, attrs={'class': "form-control"})) title = forms.CharField(max_length=20, min_length=5, error_messages={'required': u'标题不能为空', 'min_length': u'标题最少为5个字符', 'max_length': u'标题最多为20个字符'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'标题5-20个字符'})) memo = forms.CharField(required=False, max_length=256, widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3})) phone = forms.CharField(validators=[mobile_validate, ], error_messages={'required': u'手机不能为空'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'手机号码'})) email = forms.EmailField(required=False, error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'}, widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'})) Form Form
4.8 分页
分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
1 #!/usr/bin/env python 2 # _*_coding:utf-8_*_ 3 from django.utils.safestring import mark_safe 4 5 class PageInfo(object): 6 def __init__(self,current,totalItem,peritems=5): 7 self.__current=current 8 self.__peritems=peritems 9 self.__totalItem=totalItem 10 def From(self): 11 return (self.__current-1)*self.__peritems 12 def To(self): 13 return self.__current*self.__peritems 14 def TotalPage(self): #总页数 15 result=divmod(self.__totalItem,self.__peritems) 16 if result[1]==0: 17 return result[0] 18 else: 19 return result[0]+1 20 21 def Custompager(baseurl,currentPage,totalpage): #基础页,当前页,总页数 22 perPager=11 23 #总页数<11 24 #0 -- totalpage 25 #总页数>11 26 #当前页大于5 currentPage-5 -- currentPage+5 27 #currentPage+5是否超过总页数,超过总页数,end就是总页数 28 #当前页小于5 0 -- 11 29 begin=0 30 end=0 31 if totalpage <= 11: 32 begin=0 33 end=totalpage 34 else: 35 if currentPage>5: 36 begin=currentPage-5 37 end=currentPage+5 38 if end > totalpage: 39 end=totalpage 40 else: 41 begin=0 42 end=11 43 pager_list=[] 44 if currentPage<=1: 45 first="<a href=''>首页</a>" 46 else: 47 first="<a href='%s%d'>首页</a>" % (baseurl,1) 48 pager_list.append(first) 49 50 if currentPage<=1: 51 prev="<a href=''>上一页</a>" 52 else: 53 prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1) 54 pager_list.append(prev) 55 56 for i in range(begin+1,end+1): 57 if i == currentPage: 58 temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i) 59 else: 60 temp="<a href='%s%d'>%d</a>" % (baseurl,i,i) 61 pager_list.append(temp) 62 if currentPage>=totalpage: 63 next="<a href='#'>下一页</a>" 64 else: 65 next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1) 66 pager_list.append(next) 67 if currentPage>=totalpage: 68 last="<a href=''>末页</a>" 69 else: 70 last="<a href='%s%d'>末页</a>" % (baseurl,totalpage) 71 pager_list.append(last) 72 result=''.join(pager_list) 73 return mark_safe(result) #把字符串转成html语言
4.9 cookie 和Session 的操作
操作Cookie
获取cookie:request.COOKIES[key]
设置cookie:response.set_cookie(key,value)
由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。
1 <script src='/static/js/jquery.cookie.js'></script> 2 $.cookie("list_pager_num", 30,{ path: '/' });
操作Session
获取session:request.session[key]
设置session:reqeust.session[key] = value
删除session:del request[key]
1 request.session.set_expiry(value) 2 * 如果value是个整数,session会在些秒数后失效。 3 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 4 * 如果value是0,用户关闭浏览器session就会失效。 5 * 如果value是None,session会依赖全局session失效策略。
简单应用:
def login(func): def wrap(request, *args, **kwargs): # 如果未登陆,跳转到指定页面 if request.path == '/test/': return redirect('http://www.baidu.com') return func(request, *args, **kwargs) return wrap