首页 > 代码库 > Python全栈开发之21、django
Python全栈开发之21、django
http://www.cnblogs.com/wupeiqi/articles/5237704.html
http://www.cnblogs.com/wupeiqi/articles/5246483.html
http://www.cnblogs.com/yuanchenqi/articles/5786089.html
基本配置
一 常用命令
django-admin startproject sitename
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 createsuperuser
二、数据库配置(mysql)
DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘:‘dbname‘, ‘USER‘: ‘root‘, ‘PASSWORD‘: ‘xxx‘, ‘HOST‘: ‘‘, ‘PORT‘: ‘‘, }}# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替# 如下设置放置的与project同名的配置的 __init__.py文件中 import pymysqlpymysql.install_as_MySQLdb()
三、配置模板和静态文件
TEMPLATE_DIRS = ( os.path.join(BASE_DIR,‘templates‘), )
‘DIRS‘: [os.path.join(BASE_DIR, ‘templates‘), ],
STATICFILES_DIRS = ( os.path.join(BASE_DIR,‘static‘), ) # 特有的静态文件夹放在app里面, # 模板里面使用静态文件 <script src="http://www.mamicode.com/static/jquery-1.12.4.js"></script>
最后记得在setting里面注册app
Django流程
一、MTV模式
MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
路由系统
URL模式以及要为该URL模式调用的视图函数之间的映射表,每个路由对应一个view中的函数,对于这个URL调用这段代码,对于那个URL调用那段代码
参数说明:
- 一个正则表达式字符串
- 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 可选的要传递给视图函数的默认参数(字典形式)
- 一个可选的name参数
传递的参数始终是字符串
from django.conf.urls import url from . import views urlpatterns = [ # 一般 url(r‘^articles/2003/$‘, views.special_case_2003), url(r‘^articles/([0-9]{4})/$‘, views.year_archive), url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$‘, views.month_archive), # 路由分发 url(r‘^contact/‘, include(‘django_website.contact.urls‘)), # 传给视图的默认参数,对应的视图函数也必须加上同名的参数 url(r‘^blog/(?P<year>[0-9]{4})/$‘, views.year_archive, {‘foo‘: ‘bar‘}), #name参数 url(r‘^index‘,views.index,name=‘bieming‘), ]
常见写法实例
urlpatterns = [ url(r‘car‘, views.car, {‘name‘: ‘jaon‘},), url(r‘index‘, views.index, name=‘alias_login‘,), # url(r‘index55555‘, views.index, name=‘alias_login‘,),]def car(request, name): return HttpResponse(‘car‘+name)def index(request,): if request.method == ‘POST‘: username = request.POST.get(‘username‘) print(username) if username == ‘jason‘: return HttpResponse(‘ok‘) else: return HttpResponse(‘error‘) return render(request, ‘login.html‘)<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <form action="{% url ‘alias_login‘ %}" method="post"> <input type="text" name="username"> <input type="submit" value="http://www.mamicode.com/提交"> </form></body></html>
视图函数
1、HttpRequest对象的属性:
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 Type29 # 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中的AuthenticationMiddleware36 # 时该属性才可用37 #38 # session: 唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。
HttpRequest对象的方法:get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
2、HttpResponse对象:
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:页面渲染:render,render_to_response,
页面跳转:redirect
locals: 可以直接将函数中所有的变量传给模板
django的ORM
这里先创建几张表,分别是一对多和多对多,其中一对一就是一对多的时候外键唯一
1 from django.db import models 2 3 # Create your models here. 4 5 6 class UserType(models.Model): 7 nid = models.AutoField(primary_key=True) 8 caption = models.CharField(max_length=32) 9 10 11 class UserInfo(models.Model):12 user = models.CharField(max_length=16)13 pwd = models.CharField(max_length=16)14 email = models.EmailField()15 userType = models.ForeignKey(UserType)16 17 18 class Group(models.Model):19 name = models.CharField(max_length=16)20 h2g = models.ManyToManyField(‘Host‘)21 22 23 class Host(models.Model):24 hostname = models.CharField(max_length=16)25 ip = models.CharField(max_length=16)
下面来看一下表的增删改查的简单操作
1 # 第一种方式创建 2 # usertype = models.UserType(caption=‘管理员‘) 3 # usertype.save() 4 5 # 第二种方式创建 6 # models.UserType.objects.create(caption=‘普通用户‘) 7 8 # 第三种 9 # userTypeDict = {‘caption‘: ‘协管员‘}10 # models.UserType.objects.create(**userTypeDict)11 12 # 带外键添加数据库 推荐使用13 # userInfoDict = {14 # ‘user‘: ‘jason‘,15 # ‘email‘: ‘jason123@qq.com‘,16 # ‘pwd‘: ‘123‘,17 # ‘userType_id‘: 2,18 # }19 20 # userInfoDict = {21 # ‘user‘: ‘jason2‘,22 # ‘email‘: ‘jason26663@qq.com‘,23 # ‘pwd‘: ‘123‘,24 # ‘userType‘: models.UserType.objects.filter(nid=2).first(),25 # }26 27 # models.UserInfo.objects.create(**userInfoDict)28 29 # 删除30 # models.UserType.objects.filter(nid=3).delete()31 32 # 修改33 # models.UserType.objects.filter(nid=1).update(caption=‘超级管理员‘)34 35 36 37 # 查询 查询结果是QuerySet38 # ret = models.UserType.objects.all() # select会获取所有的映射39 # print(type(ret), ret, ret.query) # ret 里面保存的是对象40 41 # ret = models.UserType.objects.all().values(‘nid‘) # 获取指定映射42 # print(type(ret), ret, ret.query) # ret 里面保存的是字典43 44 # ret = models.UserType.objects.all().values_list(‘nid‘) # 获取指定映射45 # print(type(ret), ret, ret.query) # ret 里面保存的是元祖
再来看一下一对多连表查找操作
1 # 连表 双下划线使用,注意什么情况下使用 表名_set 什么情况下使用 表名__字段 2 # (表名_set 获取QuerySet对象) (表名__字段,查找过滤映射的时候用) 3 4 # 正向查找,再多的一方查找一的一方 5 # ret = models.UserInfo.objects.all().values(‘user‘, ‘userType__caption‘) 6 # print(ret) 7 8 # ret = models.UserInfo.objects.filter(userType__caption="普通用户").values(‘user‘, ‘userType__caption‘) 9 # print(ret)10 11 # 反向查找 在一的一方查找多的一方12 # 在获取了一对多中一那一方的对象之后,要获取多的那一方对象使用反向表名_set13 # ret = models.UserType.objects.filter(caption=‘普通用户‘).first()14 # print(ret.nid, ret.userinfo_set, ret.userinfo_set.all(), ret.userinfo_set.all()[0].user)15 16 # 直接在一对多一那一方使用查找或者过滤映射的时候使用反向表名__字段17 # ret = models.UserType.objects.all().values(‘caption‘, ‘userinfo__user‘)18 # print(ret)
最后看一下多对多连表查找操作
1 ‘‘‘ 2 创建表: 3 直接使用m2m 4 自已定义第三张表 5 自已定义第三张表 + m2m(through) 可以通过through参数来指明存在的表 6 7 直接使用m2m 8 --- 获取值 9 add添加10 remove删除(关系表),filter.delete()(关系表+..)11 set设置(添加、删除)12 get_or_create13 update_or_create14 15 自已定义第三张表 + m2m + through16 --关系表只能获取值 filter,all...17 通过第三张表进行操作18 19 20 ‘‘‘21 ‘‘‘22 # 直接使用23 class Host(models.Model):24 hid = models.AutoField(primary_key=True)25 hostname = models.CharField(max_length=32)26 ip = models.CharField(max_length=32)27 # h2g = models.ManyToManyField(‘Group‘)28 class Group(models.Model):29 gid = models.AutoField(primary_key=True)30 name = models.CharField(max_length=16)31 32 h2g = models.ManyToManyField(‘Host‘)33 34 35 36 # 自定义第三张表37 # class Host(models.Model):38 # hid = models.AutoField(primary_key=True)39 # hostname = models.CharField(max_length=32)40 # ip = models.CharField(max_length=32)41 # # h2g = models.ManyToManyField(‘Group‘, through=‘HostToGroup‘)42 # class Group(models.Model):43 # gid = models.AutoField(primary_key=True)44 # name = models.CharField(max_length=16)45 #46 # h2g = models.ManyToManyField(‘Host‘)47 #48 # class HostToGroup(models.Model):49 # hgid = models.AutoField(primary_key=True)50 # host_id = models.ForeignKey(‘Host‘)51 # group_id = models.ForeignKey(‘Group‘)52 # status = models.IntegerField()53 # class Meta:54 # # index_together = ("host_id",‘goup_id‘) 组合索引55 # unique_together = [56 # (‘host_id‘, ‘group_id‘), 组合唯一索引57 # ]58 59 ‘‘‘
1 # 将多台机器分给一组 正向 2 # obj = models.Group.objects.get(id=1) 3 4 # hosts = models.Host.objects.filter(id__gt=2) 5 # obj.h2g.add(*hosts) 6 7 # host = models.Host.objects.get(id=2) 8 # obj.h2g.add(host) 9 10 # 给多个组分一台机器 反向11 # h = models.Host.objects.get(id=1)12 # h.group_set.add(*models.Group.objects.filter(id__gt=2))13 # h.group_set.add(2) # 可以直接添加id或对象14 15 16 17 # h.group_set.remove(*models.Group.objects.filter(id__gt=3)) # 只删除关系表18 # h.group_set.filter(id__gt=2).delete() # group_id>2 的关系表删除了,相应的group表数据也被删除了19 20 # h.group_set.set(models.Group.objects.filter(id__gt=1), clear=True) #大于1的全部清除在添加21 22 # h.group_set.set(models.Group.objects.filter(id__gt=2)) # 大于2 以前存在的不清除,不存在的添加23 24 # h.group_set.set(models.Group.objects.filter(id__gt=4)) # 小于5的被清除25 26 # r = h.group_set.update_or_create(name=‘人事部‘) # 两张表都不存在,先在group表创建在添加到关系表中去27 # print(r)28 29 # r = h.group_set.update_or_create(name=‘pm‘) # 和上面的效果一样,为什么30 31 # h.group_set.get_or_create(name=‘te‘) # 和上面的效果一样
补充:
一次插入多条数据
author_list = [] for i in range(7): name = ‘alex‘ + str(i) age = i author = models.Author(name=name, age=age) author_list.append(author) models.Author.objects.bulk_create(author_list)
1 1、models.AutoField 自增列 = int(11) 2 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 3 2、models.CharField 字符串字段 4 必须 max_length 参数 5 3、models.BooleanField 布尔类型=tinyint(1) 6 不能为空,Blank=True 7 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 8 继承CharField,所以必须 max_lenght 参数 9 5、models.DateField 日期类型 date10 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。11 6、models.DateTimeField 日期类型 datetime12 同DateField的参数13 7、models.Decimal 十进制小数类型 = decimal14 必须指定整数位max_digits和小数位decimal_places15 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar16 对字符串进行正则表达式17 9、models.FloatField 浮点类型 = double18 10、models.IntegerField 整形19 11、models.BigIntegerField 长整形20 integer_field_ranges = {21 ‘SmallIntegerField‘: (-32768, 32767),22 ‘IntegerField‘: (-2147483648, 2147483647),23 ‘BigIntegerField‘: (-9223372036854775808, 9223372036854775807),24 ‘PositiveSmallIntegerField‘: (0, 32767),25 ‘PositiveIntegerField‘: (0, 2147483647),26 }27 12、models.IPAddressField 字符串类型(ip4正则表达式)28 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)29 参数protocol可以是:both、ipv4、ipv630 验证时,会根据设置报错31 14、models.NullBooleanField 允许为空的布尔类型32 15、models.PositiveIntegerFiel 正Integer33 16、models.PositiveSmallIntegerField 正smallInteger34 17、models.SlugField 减号、下划线、字母、数字35 18、models.SmallIntegerField 数字36 数据库中的字段有:tinyint、smallint、int、bigint37 19、models.TextField 字符串=longtext38 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]39 21、models.URLField 字符串,地址正则表达式40 22、models.BinaryField 二进制41 23、models.ImageField 图片42 24、models.FilePathField 文件
1 1、null=True 2 数据库中字段是否可以为空 3 2、blank=True 4 django的 Admin 中添加数据时是否可允许空值 5 3、primary_key = False 6 主键,对AutoField设置主键后,就会代替原来的自增 id 列 7 4、auto_now 和 auto_now_add 8 auto_now 自动创建---无论添加或修改,都是当前操作的时间 9 auto_now_add 自动创建---永远是创建时的时间10 5、choices11 GENDER_CHOICE = (12 (u‘M‘, u‘Male‘),13 (u‘F‘, u‘Female‘),14 )15 gender = models.CharField(max_length=2,choices = GENDER_CHOICE)16 6、max_length17 7、default 默认值18 8、verbose_name Admin中字段的显示名称19 9、name|db_column 数据库中的字段名称20 10、unique=True 不允许重复21 11、db_index = True 数据库索引22 12、editable=True 在Admin里是否可编辑23 13、error_messages=None 错误提示24 14、auto_created=False 自动创建25 15、help_text 在Admin中提示帮助信息26 16、validators=[]27 17、upload-to
1 # 获取个数 2 # 3 # models.Tb1.objects.filter(name=‘seven‘).count() 4 5 # 大于,小于 6 # 7 # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 8 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 9 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值10 11 # in12 #13 # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据14 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in15 16 # contains17 #18 # models.Tb1.objects.filter(name__contains="ven")19 # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感20 # models.Tb1.objects.exclude(name__icontains="ven")21 22 # range23 #24 # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and25 26 # 其他类似27 #28 # startswith,istartswith, endswith, iendswith,29 30 # order by31 #32 # models.Tb1.objects.filter(name=‘seven‘).order_by(‘id‘) # asc33 # models.Tb1.objects.filter(name=‘seven‘).order_by(‘-id‘) # desc34 35 # limit 、offset36 #37 # models.Tb1.objects.all()[10:20]38 39 # group by40 from django.db.models import Count, Min, Max, Sum41 # models.Tb1.objects.filter(c1=1).values(‘id‘).annotate(c=Count(‘num‘))42 # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
示例、用Q进行简单搜索
1 from django.shortcuts import render,HttpResponse 2 from app01 import models 3 # Create your views here. 4 import json 5 def test(request): 6 # models.BookType.objects.create(caption=‘技术‘) 7 # models.BookType.objects.create(caption=‘文学‘) 8 # models.BookType.objects.create(caption=‘动漫‘) 9 # models.BookType.objects.create(caption=‘男人装‘)10 11 # models.Book.objects.create(name=‘文艺复兴‘,pages=‘100‘,price=‘40‘,pubdate=‘1992-11-2‘,book_type_id=‘1‘)12 # models.Book.objects.create(name=‘解密‘,pages=‘80‘,price=‘10‘, pubdate=‘2016-6-10‘,book_type_id=‘2‘)13 # models.Book.objects.create(name=‘刀锋‘,pages=‘50‘,price=‘3‘, pubdate=‘2014-02-16‘,book_type_id=‘2‘)14 # models.Book.objects.create(name=‘查令十字路84号‘,pages=‘260‘,price=‘40‘,pubdate=‘1999-10-12‘,book_type_id=‘3‘)15 # models.Book.objects.create(name=‘红楼‘,pages=‘1000‘,price=‘500‘, pubdate=‘1760-1-1‘,book_type_id=‘3‘)16 # models.Book.objects.create(name=‘将夜‘,pages=‘2000‘,price=‘300‘, pubdate=‘2010-3-3‘,book_type_id=‘1‘)17 # models.Book.objects.create(name=‘mysql从删库到跑路‘,pages=‘20‘,price=‘10‘,pubdate=‘1998-9-2‘,book_type_id=‘4‘)18 # models.Book.objects.create(name=‘马克思主义‘,pages=‘50‘,price=‘100‘,pubdate=‘1937-3-3‘,book_type_id=‘2‘)19 20 return HttpResponse(‘ok‘)21 22 import json23 from datetime import date24 from datetime import datetime25 from decimal import Decimal26 class JsonCustomEncoder(json.JSONEncoder):27 28 def default(self, field):29 30 if isinstance(field, datetime):31 return field.strftime(‘%Y-%m-%d %H:%M:%S‘)32 elif isinstance(field, date):33 return field.strftime(‘%Y-%m-%d‘)34 elif isinstance(field, Decimal):35 return str(field)36 else:37 return json.JSONEncoder.default(self, field)38 39 def index(request):40 if request.method == ‘POST‘:41 ret = {‘status‘: False, ‘message‘: ‘‘, ‘data‘:None}42 try:43 post_data = http://www.mamicode.com/request.POST.get(‘post_data‘,None)44 post_data_dict = json.loads(post_data)45 print(post_data_dict)46 # {‘name‘: [‘11‘, ‘sdf‘],‘price‘: [‘11‘, ‘sdf‘]}47 # 构造搜索条件48 from django.db.models import Q49 con = Q()50 for k,v in post_data_dict.items():51 q = Q()52 q.connector = ‘OR‘53 for item in v:54 q.children.append((k, item))55 con.add(q, ‘AND‘)56 """57 ret = models.Book.objects.filter(con)58 print(ret) # queryset,[对象]59 60 from django.core import serializers61 data = http://www.mamicode.com/serializers.serialize("json", ret)62 print(type(data),data)63 # 字符串64 """65 """66 #ret = models.Book.objects.filter(con).values(‘name‘,‘book_type__caption‘)67 ret = models.Book.objects.filter(con).values_list(‘name‘, ‘book_type__caption‘)68 print(ret,type(ret))69 li = list(ret)70 data = http://www.mamicode.com/json.dumps(li)>71 print(data,type(data))72 """73 result = models.Book.objects.filter(con).values(‘name‘,‘price‘,‘pubdate‘,‘book_type__caption‘)74 # ret = models.Book.objects.filter(con).values_list(‘name‘, ‘book_type__caption‘)75 li = list(result)76 ret[‘status‘] = True77 ret[‘data‘] = li78 except Exception as e:79 ret[‘message‘] = str(e)80 ret_str = json.dumps(ret, cls=JsonCustomEncoder)81 return HttpResponse(ret_str)82 return render(request, ‘index.html‘)
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 .left{ 8 float: left; 9 } 10 .clearfix:after{ 11 content: ‘.‘; 12 clear: both; 13 display: block; 14 visibility: hidden; 15 height: 0; 16 } 17 </style> 18 </head> 19 <body> 20 <div class="condition"> 21 <div class="item clearfix"> 22 <div class="icon left" onclick="AddCondition(this);">+</div> 23 <div class="left"> 24 <select onchange="ChangeName(this);"> 25 <option value="name">书名</option> 26 <option value="book_type__caption">图书类型</option> 27 <option value="price">价格</option> 28 <option value="pages">页数</option> 29 </select> 30 </div> 31 <div class="left"><input type="text" name="name" /></div> 32 </div> 33 </div> 34 <div> 35 <input type="button" onclick="Search();" value="搜索" /> 36 </div> 37 38 <div class="container"> 39 40 </div> 41 42 43 44 <script src="/static/jquery-1.12.4.js"></script> 45 <script> 46 function AddCondition(ths) { 47 var new_tag = $(ths).parent().clone(); 48 new_tag.find(‘.icon‘).text(‘-‘); 49 new_tag.find(‘.icon‘).attr(‘onclick‘, ‘RemoveCondition(this);‘); 50 51 $(ths).parent().parent().append(new_tag); 52 } 53 function RemoveCondition(ths) { 54 $(ths).parent().remove(); 55 } 56 function ChangeName(ths) { 57 var v = $(ths).val(); 58 $(ths).parent().next().find(‘input‘).attr(‘name‘,v); 59 } 60 function Search() { 61 var post_data_dict = {}; 62 63 // 获取所有input的内容,提交数据 64 $(‘.condition input‘).each(function () { 65 // console.log($(this)[0]) 66 var n = $(this).attr(‘name‘); 67 var v = $(this).val(); 68 var v_list = v.split(‘,‘); 69 post_data_dict[n] = v_list; 70 }); 71 console.log(post_data_dict); 72 var post_data_str = JSON.stringify(post_data_dict); 73 $.ajax({ 74 url: ‘/index/‘, 75 type: ‘POST‘, 76 data: { ‘post_data‘: post_data_str}, 77 dataType: ‘json‘, 78 success: function (arg) { 79 // 字符串 "<table>" + 80 if(arg.status){ 81 var table = document.createElement(‘table‘); 82 table.setAttribute(‘border‘,1); 83 // [{,name,pubdate,price,caption},] 84 $.each(arg.data, function(k,v){ 85 var tr = document.createElement(‘tr‘); 86 87 var td1 = document.createElement(‘td‘); 88 td1.innerText = v[‘name‘]; 89 var td2 = document.createElement(‘td‘); 90 td2.innerText = v[‘price‘]; 91 var td3 = document.createElement(‘td‘); 92 td3.innerText = v[‘book_type__caption‘]; 93 var td4 = document.createElement(‘td‘); 94 td4.innerText = v[‘pubdate‘]; 95 tr.appendChild(td1); 96 tr.appendChild(td2); 97 tr.appendChild(td3); 98 tr.appendChild(td4); 99 100 table.appendChild(tr);101 });102 103 $(‘.container‘).empty();104 $(‘.container‘).append(table);105 }else{106 alert(arg.message);107 }108 109 }110 111 })112 }113 </script>114 </body>115 </html>
1 from django.db import models 2 3 # Create your models here. 4 5 6 class Author(models.Model): 7 name = models.CharField(max_length=32) 8 age = models.IntegerField() 9 10 11 class BookType(models.Model):12 caption = models.CharField(max_length=32)13 14 15 class Book(models.Model):16 name = models.CharField(max_length=64)17 price = models.DecimalField(max_digits=10, decimal_places=2)18 pubdate = models.DateField()19 20 authors = models.ManyToManyField(Author)21 book_type = models.ForeignKey(BookType)
1 from django.shortcuts import render,HttpResponse 2 from app01 import models 3 # Create your views here. 4 import json 5 def test(request): 6 # models.BookType.objects.create(caption=‘技术‘) 7 # models.BookType.objects.create(caption=‘文学‘) 8 # models.BookType.objects.create(caption=‘动漫‘) 9 # models.BookType.objects.create(caption=‘男人装‘)10 11 # models.Book.objects.create(name=‘文艺复兴‘,pages=‘100‘,price=‘40‘,pubdate=‘1992-11-2‘,book_type_id=‘1‘)12 # models.Book.objects.create(name=‘解密‘,pages=‘80‘,price=‘10‘, pubdate=‘2016-6-10‘,book_type_id=‘2‘)13 # models.Book.objects.create(name=‘刀锋‘,pages=‘50‘,price=‘3‘, pubdate=‘2014-02-16‘,book_type_id=‘2‘)14 # models.Book.objects.create(name=‘查令十字路84号‘,pages=‘260‘,price=‘40‘,pubdate=‘1999-10-12‘,book_type_id=‘3‘)15 # models.Book.objects.create(name=‘红楼‘,pages=‘1000‘,price=‘500‘, pubdate=‘1760-1-1‘,book_type_id=‘3‘)16 # models.Book.objects.create(name=‘将夜‘,pages=‘2000‘,price=‘300‘, pubdate=‘2010-3-3‘,book_type_id=‘1‘)17 # models.Book.objects.create(name=‘mysql从删库到跑路‘,pages=‘20‘,price=‘10‘,pubdate=‘1998-9-2‘,book_type_id=‘4‘)18 # models.Book.objects.create(name=‘马克思主义‘,pages=‘50‘,price=‘100‘,pubdate=‘1937-3-3‘,book_type_id=‘2‘)19 20 return HttpResponse(‘ok‘)21 22 import json23 from datetime import date24 from datetime import datetime25 from decimal import Decimal26 class JsonCustomEncoder(json.JSONEncoder):27 28 def default(self, field):29 30 if isinstance(field, datetime):31 return field.strftime(‘%Y-%m-%d %H:%M:%S‘)32 elif isinstance(field, date):33 return field.strftime(‘%Y-%m-%d‘)34 elif isinstance(field, Decimal):35 return str(field)36 else:37 return json.JSONEncoder.default(self, field)38 39 def index(request):40 if request.method == ‘POST‘:41 ret = {‘status‘: False, ‘message‘: ‘‘, ‘data‘:None}42 try:43 post_data = http://www.mamicode.com/request.POST.get(‘post_data‘,None)44 post_data_dict = json.loads(post_data)45 print(post_data_dict)46 # {‘name‘: [‘11‘, ‘sdf‘],‘price‘: [‘11‘, ‘sdf‘]}47 # 构造搜索条件48 from django.db.models import Q49 con = Q()50 for k,v in post_data_dict.items():51 q = Q()52 q.connector = ‘OR‘53 for item in v:54 q.children.append((k, item))55 con.add(q, ‘AND‘)56 """57 ret = models.Book.objects.filter(con)58 print(ret) # queryset,[对象]59 60 from django.core import serializers61 data = http://www.mamicode.com/serializers.serialize("json", ret) # 这种方法获取到的图书类型是id不是book_type__caption62 print(type(data),data)63 # 字符串64 """65 """66 #ret = models.Book.objects.filter(con).values(‘name‘,‘book_type__caption‘)67 ret = models.Book.objects.filter(con).values_list(‘name‘, ‘book_type__caption‘)68 print(ret,type(ret))69 li = list(ret)70 data = http://www.mamicode.com/json.dumps(li)>71 print(data,type(data))72 """73 result = models.Book.objects.filter(con).values(‘name‘,‘price‘,‘pubdate‘,‘book_type__caption‘)74 # ret = models.Book.objects.filter(con).values_list(‘name‘, ‘book_type__caption‘)75 li = list(result)76 ret[‘status‘] = True77 ret[‘data‘] = li78 except Exception as e:79 ret[‘message‘] = str(e)80 ret_str = json.dumps(ret, cls=JsonCustomEncoder)81 return HttpResponse(ret_str)82 return render(request, ‘index.html‘)
form验证
1 #!/usr/bin/env python 2 # coding=utf-8 3 4 from django import forms 5 6 7 class Forml(forms.Form): 8 # username = forms.CharField() 9 # pwd = forms.CharField()10 11 user = forms.CharField(12 widget=forms.TextInput(attrs={13 ‘class‘: ‘c1‘,14 }),15 error_messages={16 ‘required‘: ‘用户名不能为空‘,17 },18 )19 pwd = forms.CharField(max_length=4, min_length=2)20 21 # email = forms.EmailField(22 # error_messages={23 # ‘required‘: ‘邮箱不能为空‘,24 # ‘invalid‘: ‘邮箱格式错误‘,25 # }26 # )27 email = forms.EmailField(28 error_messages={29 ‘required‘: ‘邮箱不能为空‘,30 ‘invalid‘: ‘邮箱格式错误‘31 }32 )33 34 memo = forms.CharField(35 widget=forms.Textarea()36 )37 38 # 自定义39 user_type_choice = (40 (0, ‘普通用户‘),41 (1, ‘高级用户‘),42 )43 # 如果从数据库查找,则Forml里面定义的静态字段只会执行一次44 # user_type_choice = models.BookType.objects.values_list(‘id‘, ‘caption‘)45 book_type = forms.CharField(46 widget=forms.widgets.Select(47 choices=user_type_choice,48 attrs={‘class‘: "form-control"},49 )50 )51 52 # 数据库动态的53 # 如果从数据库查找,则Forml里面定义的静态字段只会执行一次,所以需要下面动态的54 # def __init__(self, *args, **kwargs):55 # super(Forml, self).__init__(*args, **kwargs)56 # self.fields[‘book_type‘] = forms.CharField(57 # widget=forms.widgets.Select(58 # choices=models.BookType.objects.values_list(‘id‘, ‘caption‘),59 # attrs={‘class‘: "form-control"},60 # )61 # )
1 #!/usr/bin/env python 2 # coding=utf-8 3 4 from django.shortcuts import render 5 6 from django.http import HttpResponse 7 8 from form1.forms import Forml 9 10 11 def form1(req):12 f = Forml()13 if req.method == ‘POST‘:14 f = Forml(req.POST)15 if f.is_valid():16 print(f.cleaned_data)17 else:18 # print(f.errors.get(‘user‘,None))19 # print(f.errors[‘pwd‘][0])20 # print(type(f.errors),f.errors)21 # from django.forms.utils import ErrorDict22 23 print(type(f.errors), f.errors)24 return render(req, ‘account/form1.html‘, {‘error‘: f.errors, ‘form‘: f})25 return render(req, ‘account/form1.html‘, {‘form‘: f})
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> span{ background-color: darkolivegreen; } </style></head><body><form action="/form1/" method="POST"> <div> <!--<input type="text" name="username">--> {{form.user}} {% if error.user %} <span>{{error.user.0}}</span> {% endif %} </div> <div> {{form.pwd}} <!--<input type="text" name="password">--> {% if error.pwd %} <span>{{error.pwd.0}}</span> {% endif %} </div> <div> {{form.email}} {% if error.email %} <span>{{error.email.0}}</span> {% endif %} </div> <div> {{form.memo}} {% if error.memo %} <span>{{error.memo.0}}</span> {% endif %} </div> <div> {{form.book_type}} {% if error.book_type %} <span>{{error.book_type.0}}</span> {% endif %} </div> <button type="submit">提交</button> <!--<input type="submit" value=http://www.mamicode.com/"提交"/>--> </form></body></html>
除此之外还支持自定义字段,具体用法看下面的使用
import refrom django import formsfrom django.core.exceptions import ValidationErrordef 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): # 这里手机号使用了自己自定义的验证规则 phone = forms.CharField(validators=[mobile_validate, ], error_messages={‘required‘: u‘手机不能为空‘}, widget=forms.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘手机号码‘}))
cookie和session
一、cookie
1 rep = HttpResponse(...) 或 rep = render(request, ...) 2 3 rep.set_cookie(key,value,...) 4 rep.set_signed_cookie(key,value,salt=‘加密盐‘,...) 5 参数: 6 key, 键 7 value=http://www.mamicode.com/‘‘, 值 8 max_age=None, 超时时间 9 expires=None, 超时时间(IE requires expires, so set it if hasn‘t been already.)10 path=‘/‘, Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问11 domain=None, Cookie生效的域名12 secure=False, https传输13 httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
二、session
1 a. 配置 settings.py 2 3 SESSION_ENGINE = ‘django.contrib.sessions.backends.db‘ # 引擎(默认) 4 5 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) 6 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) 7 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) 8 SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) 9 SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)10 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)11 SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)12 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)13 14 15 16 b. 使用17 18 def index(request):19 # 获取、设置、删除Session中数据20 request.session[‘k1‘]21 request.session.get(‘k1‘,None)22 request.session[‘k1‘] = 12323 request.session.setdefault(‘k1‘,123) # 存在则不设置24 del request.session[‘k1‘]25 26 # 所有 键、值、键值对27 request.session.keys()28 request.session.values()29 request.session.items()30 request.session.iterkeys()31 request.session.itervalues()32 request.session.iteritems()33 34 35 # 用户session的随机字符串36 request.session.session_key37 38 # 将所有Session失效日期小于当前日期的数据删除39 request.session.clear_expired()40 41 # 检查 用户session的随机字符串 在数据库中是否42 request.session.exists("session_key")43 44 # 删除当前用户的所有Session数据45 request.session.delete("session_key")46 47 ...
a. 配置 settings.py SESSION_ENGINE = ‘django.contrib.sessions.backends.cache‘ # 引擎 SESSION_CACHE_ALIAS = ‘default‘ # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存 b. 使用 同上
1 a. 配置 settings.py 2 3 SESSION_ENGINE = ‘django.contrib.sessions.backends.file‘ # 引擎 4 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T 5 6 7 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 8 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 9 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名10 SESSION_COOKIE_SECURE = False # 是否Https传输cookie11 SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输12 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)13 SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期14 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存15 16 b. 使用17 18 同上
1 数据库用于做持久化,缓存用于提高效率2 3 a. 配置 settings.py4 5 SESSION_ENGINE = ‘django.contrib.sessions.backends.cached_db‘ # 引擎6 7 b. 使用8 9 同上
1 a. 配置 settings.py 2 3 SESSION_ENGINE = ‘django.contrib.sessions.backends.signed_cookies‘ # 引擎 4 5 b. 使用 6 7 同上 8 9 10 备注:保存在客户端
三、session用户验证
def login_auth(func): def wrapper(req, *args, **kwargs): if not req.session.get(‘is_login‘, None): return redirect(‘/admin/login‘) return func(req, *args, **kwargs) return wrapper
跨站请求伪造
一、简介
django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
全局:
中间件 django.middleware.csrf.CsrfViewMiddleware
局部:
- @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
- @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
二、普通表单
veiw中设置返回值: return render_to_response(‘Account/Login.html‘,data,context_instance=RequestContext(request)) 或者 return render(request, ‘xxx.html‘, data) #这里也可以看出render 和 render_to_respone 的区别 html中设置Token: {% csrf_token %}
三、ajax发送
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 {% csrf_token %} 9 10 <input type="button" onclick="Do();" value=http://www.mamicode.com/"Do it"/>11 12 <script src=http://www.mamicode.com/"/static/plugin/jquery/jquery-1.8.0.js"></script>13 <script src=http://www.mamicode.com/"/static/plugin/jquery/jquery.cookie.js"></script>14 <script type="text/javascript">15 var csrftoken = $.cookie(‘csrftoken‘);16 17 function csrfSafeMethod(method) {18 // these HTTP methods do not require CSRF protection19 return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));20 }21 $.ajaxSetup({22 beforeSend: function(xhr, settings) {23 if (!csrfSafeMethod(settings.type) && !this.crossDomain) {24 xhr.setRequestHeader("X-CSRFToken", csrftoken);25 }26 }27 });28 function Do(){29 30 $.ajax({31 url:"/app01/test/",32 data:{id:1},33 type:‘POST‘,34 success:function(data){35 console.log(data);36 }37 });38 39 }40 </script>41 </body>42 </html>
1 from django.template.context import RequestContext 2 # Create your views here. 3 4 5 def test(request): 6 7 if request.method == ‘POST‘: 8 print request.POST 9 return HttpResponse(‘ok‘)10 return render_to_response(‘app01/test.html‘,context_instance=RequestContext(request))11 12 # https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
django序列化
一、serializers
1 # 缺点外键字段不能很好显示2 3 from django.core import serializers4 5 ret = models.BookType.objects.all()6 7 data = http://www.mamicode.com/serializers.serialize("json", ret)
二、json
有些数据结构不支持,這里可以通过自定义处理器来做扩展
import json from datetime import date from datetime import datetimeclass JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, datetime): return field.strftime(‘%Y-%m-%d %H:%M:%S‘) elif isinstance(field, date): return field.strftime(‘%Y-%m-%d‘) elif isinstance(field, Decimal): return str(field) else: return json.JSONEncoder.default(self, field)ret_str = json.dumps(ret, cls=JsonCustomEncoder)
django自定义分页
和tornado一样,只需修改一个地方
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 from django.utils.safestring import mark_safe 5 6 7 class Pagination: 8 def __init__(self, current_page, all_item): 9 try:10 page = int(current_page)11 except:12 page = 113 if page < 1:14 page = 115 16 all_pager, c = divmod(all_item, 5)17 if c > 0:18 all_pager += 119 20 self.current_page = page21 self.all_pager = all_pager22 23 @property24 def start(self):25 return (self.current_page - 1) * 526 27 @property28 def end(self):29 return self.current_page * 530 31 def string_pager(self, base_url="/admin/manage/"):32 list_page = []33 if self.all_pager < 11:34 s = 135 t = self.all_pager + 136 else: # 总页数大于1137 if self.current_page < 6:38 s = 139 t = 1240 else:41 if (self.current_page + 5) < self.all_pager:42 s = self.current_page - 543 t = self.current_page + 5 + 144 else:45 s = self.all_pager - 1146 t = self.all_pager + 147 # 首页48 # first = ‘<a href="http://www.mamicode.com/%s1">首页</a>‘ % base_url49 # list_page.append(first)50 # 上一页51 # 当前页 page52 if self.current_page == 1:53 prev = ‘<a href="javascript:void(0);">上一页</a>‘54 else:55 prev = ‘<a href="http://www.mamicode.com/%s%s">上一页</a>‘ % (base_url, self.current_page - 1,)56 list_page.append(prev)57 58 for p in range(s, t): # 1-1159 if p == self.current_page:60 temp = ‘<a class="active" href="http://www.mamicode.com/%s%s">%s</a>‘ % (base_url, p, p)61 else:62 temp = ‘<a href="http://www.mamicode.com/%s%s">%s</a>‘ % (base_url, p, p)63 list_page.append(temp)64 if self.current_page == self.all_pager:65 nex = ‘<a href="javascript:void(0);">下一页</a>‘66 else:67 nex = ‘<a href="http://www.mamicode.com/%s%s">下一页</a>‘ % (base_url, self.current_page + 1,)68 69 list_page.append(nex)70 71 # 尾页72 # last = ‘<a href="http://www.mamicode.com/%s%s">尾页</a>‘ % (base_url, self.all_pager,)73 # list_page.append(last)74 75 # 跳转76 # jump = """<input type=‘text‘ /><a onclick="Jump(‘%s‘,this);">GO</a>""" % (‘/index/‘, )77 # script = """<script>78 # function Jump(baseUrl,ths){79 # var val = ths.previousElementSibling.value;80 # if(val.trim().length>0){81 # location.href = http://www.mamicode.com/baseUrl + val;82 # }83 # }84 # </script>"""85 # list_page.append(jump)86 # list_page.append(script)87 str_page = "".join(list_page)88 return mark_safe(str_page)
模板
一、基础语法
1 {{ item }} 2 {% for item in item_list %} <a>{{ item }}</a> {% endfor %} 3 forloop.counter 4 forloop.first 5 forloop.last 6 {% if ordered_warranty %} {% else %} {% endif %} 7 母板:{% block title %}{% endblock %} 8 子板:{% extends "base.html" %} 9 {% block title %}{% endblock %}10 帮助方法:11 {{ item.event_start|date:"Y-m-d H:i:s"}}12 {{ bio|truncatewords:"30" }}13 {{ my_list|first|upper }}14 {{ name|lower }}
二、自定义
1 from django import template 2 from django.utils.safestring import mark_safe 3 from django.template.base import resolve_variable, Node, TemplateSyntaxError 4 5 register = template.Library() 6 7 @register.simple_tag 8 def my_simple_time(v1,v2,v3): 9 return v1 + v2 + v310 11 @register.simple_tag12 def my_input(id,arg):13 result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘ />" %(id,arg,)14 return mark_safe(result)
在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %}
使用simple_tag
{% my_simple_time 1 2 3%}{% my_input ‘id_username‘ ‘hide‘%}
Python全栈开发之21、django