rls
url(r'show_time1/', views.show_time1) #普通匹配 url(r'^show_time2', views.show_time2) #开头以show_time2开始 url(r'show_time3$', views.show_time3) #以show_time3结尾 url(r'show_time4/\d{4}', views.show_time4) #\d{4}代表任意4个数字 url(r'show_time5/(\d{4})', views.show_time5) #无名分组,(\d{4})会传到year def show_time5(req,y): return HttpResponse(y) url(r'show_time6/(\d{4})/(\d{2})', views.show_time6) #(\d{4}),(\d{2})会分别传到year和month def show_time6(req,y,m): return HttpResponse(y,m) url(r'show_time7/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})', views.show_time7) #有名分组,\d{4}和\d{2}分别会传到year和month def show_time7(req,year,month):#这里接受的参数必须是year和month return HttpResponse(year+'+'+month)
2.views
提交方式为POST的时候在settings.py里MIDDLEWARE里把'django.middleware.csrf.CsrfViewMiddleware'删掉 def register(request): print(request.GET/POST.get("user")) if request.method=="POST/GET": return **** return ****
http请求:HttpRequest对象
http响应:HttpResponse对象
1 HttpRequest对象的属性和方法:
# path: 请求页面的全路径,不包括域名 # # method: 请求中使用的HTTP方法的字符串表示。全大写表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含所有HTTP GET参数的类字典对象 # # POST: 包含所有HTTP POST参数的类字典对象 # # 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过 # HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用 # if req.POST来判断是否使用了HTTP POST 方法;应该使用 if req.method=="POST" # # # # COOKIES: 包含所有cookies的标准Python字典对象;keys和values都是字符串。 # # FILES: 包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中 name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys: # # filename: 上传文件名,用字符串表示 # content_type: 上传文件的Content Type # content: 上传文件的原始内容 # # # user: 是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前 # 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你 # 可以通过user的is_authenticated()方法来辨别用户是否登陆: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 时该属性才可用 # # session: 唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。 #方法 get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 req.path:/index33
注意一个常用方法:request.POST.getlist('')
2 HttpResponse对象:
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染: render()(推荐)<br> render_to_response(),#不需要req参数 页面跳转: redirect("路径"),
#render和redirect的区别
render返回的页面里url不会变 locals(): 可以直接将函数中所有的变量传给模板
3.模板语言
模板语言也可以跨数据库表查询,双下划线换成.(dian)
模板语言里有.all方法,下图的空色框部分可以在前端用模板语言来写book_obj.authors.all
①变量
在前端:
<h1>hello {{name}} 时间{{ t }} {{ req.method}}</h1>
在后端里的所有的局部变量都可以拿到
后端:
方法1: def show_time1(req): t=time.ctime() return render(req,'index1.html',{'tt':t}) 方法2: def show_time2(req): ntime=time.ctime() methods=req.method return render(req,'index2.html',locals())
后端里往前端传的内容可以是:字符串,列表,字典,类
class Animal():
def __init__(self,name,sex):
self.name=name
self.sex=sex
def judian_guolvqi(req): l=['pakhm','jx',['a','b','c']]
#前端里的显示:
l:['pakhm','jx',['a','b','c']]
l.0:jx #索引
l.2.2:c
d={'name':'pakhm', 'age':12, 'hobby':'jirou'}
#前端里的显示:
d:{'name':'pakhm','age':12,'hobby':'jirou'}
d.name:pakhm c=Animal('alex','man')
#前端里的显示:
c:<app01.views.Animal object at 0x0000044445F8>,对象的内存地址
c.name:alex
========================================================
t1='test' t2='he l l o' da=datetime.datetime.now() e=[] a='<a href=''>click</a>' n=None return render(req,'index4.html',locals())
变量的过滤器使用:
语法格式: {{obj|filter:param}}
add:给变量加上相应的值
后端:
def test(req): num=10
return render(req,'test.html',locals())
前端:
<h1>{{ num|add:12 }}</h1>
页面显示的内容:
22
date:格式化日期字符串
后端: def test(req): t=datetime.datetime.now() #Feb. 28, 2017, 11:19 a.m.
return render(req,'test.html',locals()) 前端: <h1>{{ t|date:'Y-m-d' }}</h1> 页面显示的内容: 2017-02-28
# 1 add : 给变量加上相应的值 add:12 # # 2 addslashes : 给变量中的引号前加上斜线 # # 3 capfirst : 首字母大写 # # 4 cut : 从字符串中移除所有指定的字符 cut:"s" # # 5 date : 格式化日期字符串 date:'Y-m-d' # # 6 default : 如果值是False,就替换成设置的默认值,否则就是用本来的值 #空值算false # # 7 default_if_none: 如果值是None,就替换成设置的默认值,否则就使用本来的值 #实例: #value1="aBcDe" {{ value1|upper }}<br> #import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }}<br> #value5=[] {{ value5|default:'空的' }}<br> #value6='<a href="#">跳转</a>' {{ value6 }}#结果是普通的字符串形式的<a href="#">跳转</a>
方式1: {% autoescape off %} ,结果是带有a标签属性的 跳转 {{ value6 }} {% endautoescape %}
方式2: {{ value6|safe }},结果是带有a标签属性的 跳转
?? {{ value6|striptags }} #value7='1234' {{ value7|filesizeformat }}<br> {{ value7|first }}<br>#取第一个 {{ value7|length }}<br>#计算长度 {{ value7|slice:":-1" }}<br>#切片 #value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }}<br> value9='hello I am yuan'
②控制语句
基本格式: {% tags %}
可以把上面①里的变量放入到控制语句中
{% if %} 的使用 :
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大于200</p> {% else %} <p>num大于100小于200</p> {% endif %} {% elif num < 100 %} <p>num小于100</p> {% else %} <p>num等于100</p> {% endif %}
{% for %}的使用
后端:
l=["村长","正文","苍井"]
前端:
{% for name in l %}
{{ forloop.counter }} : {{ name }} #forloop.counter表示的是循环的次数,forloop.counter0循环的次数从0开始,forloop.revcounter循环的次数倒叙排,forloop.revcounter0,forloop.first是当第一次循环时值为True
{% endfor %}
网页显示结果:
1:村长 2:正文 3:苍井空
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> #在标签里添加reversed来反序循环列表: {% for obj in 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 %} #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量, #这个变量含有一些属性可以提供给你一些关于循环的信息 1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: {% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first当第一次循环时值为True,在特别情况下很有用: {% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了 # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它 # Django会在for标签的块中覆盖你定义的forloop变量的值 # 在其他非循环的地方,你的forloop变量仍然可用 #{% empty %} {{li }} {% for i in li %} <li>{{ forloop.counter0 }}----{{ i }}</li> {% empty %}#如果上面的li是空的,那么显示: <li>this is empty!</li> {% endfor %} # [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55
③其他
{%csrf_token%}:csrf_token标签
用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效
其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。
<form action="{% url 'login' %}" method="post"> <p>姓名 <input type="text" name="user"></p> <p>密码 <input type="text" name="pwd"></p> <p><input type="submit"></p> {% csrf_token %} </form> 这里加csrf_token的话提交方式为post的时候不用在settings.py删掉csrf了
{% url %}: 引用路由配置的地址
<form action="{% url "bieming"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
{% with %}:用更简单的变量名替代复杂的变量名
后端里传过来的是fhjsaldfhjsdfhlasdfhljsdal
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
{% verbatim %}: 禁止render
{% verbatim %}
{{ hello }}
{% endverbatim %}
{% load %}: 加载标签库
--自定义filter和simple_tag
------a、在app中创建templatetags包(必须的)
------b、创建任意 .py 文件,如:my_tags.py
my_tags.py内容
from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改变 #########################以上内容是必须加进去的 @register.filter def filter_multi(v1,v2): #参数只能传一个 return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2,v3): #可以传多个参数 return v1 * v2 * v3 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
------c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}
------d、使用simple_tag和filter(如何调用)
-------------------------------.html
{% load xxx %} #首行
# num=12
{{ num|filter_multi:2 }} #v1=12,v2=2,v1*v2=24
{{ num|filter_multi:"[22,333,4444]" }}#结果是[22,333,444,22,333*...*22,333,444],重复12次22,333,4444
{% simple_tag_multi 2 5 6 %} 参数不限,但不能放在if for语句中
{% simple_tag_multi num d.age 8 %}
------e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
注意:
filter可以用在if,for等语句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
{{ num|filter_multi:30 }}
{% endif %}
4.model(数据库模型)
makemigrations, migrate
字段(django model):
AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列 from django.db import models class UserInfo(models.Model): # 自动创建一个列名为id的且为自增的整数列 username = models.CharField(max_length=32) class Group(models.Model): # 自定义自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型 字段列表
django model字段对应的数据库字段:
'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)',
字段参数:
null 数据库中字段是否可以为空 db_column 数据库中字段的列名 default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引
unique_together 联合唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引//局部索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引//局部索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引//局部索引
verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_\d+', message='错误了', code='c1'), RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )
多表关系及参数:
一对多操作:
ForeignKey(ForeignObject) # ForeignObject(RelatedField) to, # 要进行关联的表名,默认不用写 to_field=None, # 要关联的表中的字段名称,默认不用写 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 - models.CASCADE,删除关联数据,与之关联也删除 - models.DO_NOTHING,删除关联数据,引发错误IntegrityError - models.PROTECT,删除关联数据,引发错误ProtectedError - models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空) - models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值) - models.SET,删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象) def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id" on_delete=models.SET(func),) related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : { 'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') db_constraint=True # 是否在数据库中创建外键约束 parent_link=False # 在Admin中是否显示关联数据
一对一操作: OneToOneField(ForeignKey) to, # 要进行关联的表名 to_field=None # 要关联的表中的字段名称 on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为 ###### 对于一对一 ###### # 1. 一对一其实就是 一对多 + 唯一索引 # 2.当两个类之间有继承关系时,默认会创建一个一对一字段 # 如下会在A表中额外增加一个c_ptr_id列且唯一: class C(models.Model): nid = models.AutoField(primary_key=True) part = models.CharField(max_length=12) class A(C): id = models.AutoField(primary_key=True) code = models.CharField(max_length=1)
多对多操作: ManyToManyField(RelatedField) to, # 要进行关联的表名 related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: # 如: - limit_choices_to={'nid__gt': 5} - limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q - limit_choices_to=Q(nid__gt=10) - limit_choices_to=Q(nid=8) | Q(nid__gt=10) - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段 # 做如下操作时,不同的symmetrical会有不同的可选字段 models.BB.objects.filter(...) # 可选字段有:code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=True) # 可选字段有: bb, code, id, m1 class BB(models.Model): code = models.CharField(max_length=12) m1 = models.ManyToManyField('self',symmetrical=False) through=None, # 自定义第三张表时,使用字段用于指定关系表 through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表 from django.db import models class Person(models.Model): name = models.CharField(max_length=50) class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField( Person, through='Membership', through_fields=('group', 'person'), ) class Membership(models.Model): group = models.ForeignKey(Group, on_delete=models.CASCADE) person = models.ForeignKey(Person, on_delete=models.CASCADE) inviter = models.ForeignKey( Person, on_delete=models.CASCADE, related_name="membership_invites", ) invite_reason = models.CharField(max_length=64) db_constraint=True, # 是否在数据库中创建外键约束 db_table=None, # 默认创建第三张表时,数据库中表的名称
①单表的增删改查
models.py
class Book(models.Model): name=models.CharField(max_length=20) price=models.IntegerField() pub_date=models.DateField() author=models.CharField(max_length=32,null=False)
#null 是针对数据库而言,如果 null=True, 表示数据库的该字段可以为空,即在Null字段显示为YES。
#blank 是针对表单的,如果 blank=True,表示django admin该字段可以不填,但是对数据库来说,没有任何影响
class Author(models.Model): name=models.CharField(max_length=32)
增:
views.py
方式1:
def addbook(req): b=Book(name="python基础",price=99,author="yuan",pub_date="2017-12-12") b.save()
return HttpResponse("添加成功")
方式2:
def addbook(req): Book.objects.create(name="python基础",price=99,author="yuan",pub_date="2017-12-12") return HttpResponse("添加成功")
改:
views.py
方式1(推荐):
def update(req): Book.objects.filter(author="yuan").update(price=999)#修改所有作者为yuan的书的价格 return HttpResponse("ok")
方式2:
def update(req): b=Book.objects.get(author="yuan")#修改所有作者为yuan的书的价格进行修改
b.price=999
b.save() return HttpResponse("ok")
删:
views.py
def delete(req): Book.objects.filter(author="oldboy").delete()#删除所有作者为oldboy的书的数据 return HttpResponse("ok")
查:
http://www.cnblogs.com/wupeiqi/articles/6216618.html
Publisher.objects.all(),.filter(),.exclude()等都只是返回了一个QuerySet
QuerySet的方法:
(1)values,取QuerySet里的具体属性
QuerySet.values("xx")/values("xx","xxx"),返回的是[{字典},{字典}]形式
QuerySet.values_list("xx")/values_list("xx","xxx"),返回的是[(元组),(元组)]形式
(2)order_by(),根据什么条件对结果进行排序(从小到大)
QuerySet.order_by("xx")#括号里可以有多个参数,参数前面加上‘减号’的话意思是逆向排序
(3)reverse(),对查询结果反向排序,要跟order_by配合使用,单独使用没效果
QuerySet.order_by("xx").reverse()
(4)distinct(),从返回结果中剔除重复纪录(所谓的重复,指的是所有的列名都一样的)
要跟values()配合使用
book_list1 = QuerySet.values("name").distinct()
(5)count(),返回QuerySet的对象数量。
QuerySet.count()
(6)exists(),如果QuerySet包含数据,就返回True(不会从数据库里拿数据过来,只判断数据有没有),否则返回False。
QuerySet.exists()
(7) select_related('跨表字段','跨表字段'/('跨表字段__跨表字段'))
性能相关:表之间进行join连表操作,一次性获取关联的数据。(连表查询性能低)
person_list=models.Person.objects.all() for row in person_list: print(row.user,row.id,row.ut_id) print(row.ut_title) 每次跨表查询的时候都会执行一次SQL语句 person_list=models.Person.objects.all('ut') for row in person_list: print(row.user,row.id,row.ut_id) print(row.ut_title) 不管进行几次跨表查询,只会执行一次SQL语句
(7.5)prefetch_related
性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。用法跟上面的一样
(8)extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
# 构造额外的查询条件或者映射,如:子查询 Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) Entry.objects.extra(where=['headline=%s'], params=['Lennon']) Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
(9)defer(),映射中排除某列数据
models.UserInfo.objects.defer('username','id') 或 models.UserInfo.objects.filter(...).defer('username','id')
(10)only(),仅取某个表中某列的数据
models.UserInfo.objects.only('username','id') 或 models.UserInfo.objects.filter(...).only('username','id')
(11)using('settings里的数据库别名')
指定使用的数据库,参数为别名(setting中的设置)
(12)raw(self, raw_query, params=None, translations=None, using=None)
# 执行原生SQL models.UserInfo.objects.raw('select * from userinfo') # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名 models.UserInfo.objects.raw('select id as nid from 其他表') # 为原生SQL设置参数 models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,]) # 将获取的到列名转换为指定列名 name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'} Person.objects.raw('SELECT * FROM some_other_table', translations=name_map) # 指定数据库 models.UserInfo.objects.raw('select * from userinfo', using="default") ################### 原生SQL ################### from django.db import connection, connections cursor = connection.cursor() # cursor = connections['default'].cursor() cursor.execute("""SELECT * from auth_user where id = %s""", [1]) row = cursor.fetchone() # fetchall()/fetchmany(..)
(13)dates(self, field_name, kind, order='ASC')
# 根据时间进行某一部分进行去重查找并截取指定内容 # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日) # order只能是:"ASC" "DESC" # 并获取转换后的时间 - year : 年-01-01 - month: 年-月-01 - day : 年-月-日 models.DatePlus.objects.dates('ctime','day','DESC')
(14)datetimes(self, field_name, kind, order='ASC', tzinfo=None)
# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间 # kind只能是 "year", "month", "day", "hour", "minute", "second" # order只能是:"ASC" "DESC" # tzinfo时区对象 models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC) models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai')) """ pip3 install pytz import pytz pytz.all_timezones #会列出来所有的时区信息 pytz.timezone(‘Asia/Shanghai’) """
(15)none(),空queryset对象
(16)bulk_create(self, objs, batch_size=None)
# 批量插入 # batch_size表示一次插入的个数 objs = [ models.DDD(name='r11'), models.DDD(name='r22') ] models.DDD.objects.bulk_create(objs, 10)#后面的参数意思是最多一次性创建x条数据
(17)get_or_create(self, defaults=None, **kwargs)
# 如果存在,则获取,否则,创建 # defaults 指定创建时,其他字段的值 obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})
(18)update_or_create(self, defaults=None, **kwargs)
# 如果存在,则更新,否则,创建 # defaults 指定创建时或更新时的其他字段 obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})
(19)in_bulk(self, id_list=None)
# 根据主键ID进行查找 id_list = [11,21,31] models.DDD.objects.in_bulk(id_list)
综合的:QuerySet..reverse().order_by("xx").values("xx"),上面的几个方法一起混合着使用的时候不分顺序
①all,查询所有结果
views.py
def select(req): book_list1=Book.objects.all()#查询book表里所有数据,book_list类型是QuerySet,每一条具体数据的集合,all()操作支持python里的切片操作
book_list2=Book.objects.all()[::-1]#倒着查询所有数据
return render(req,"index.html",{"book_list1":book_list1})
html
{% for book in book_list1 %} <div> <p>{{ book.name }} {{ book.author }} {{ book.price }}</p> </div> {% endfor %}
②first,last,查询数据里的第一个/最后一个数据
views.py
def select(req): book_list1=Book.objects.fisrt() book_list2=Book.objects.last() return render(req,"index.html")
③get(条件)
返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误
def update(req): b=Book.objects.get(author="yuan")return HttpResponse("ok")
④filter(条件)
它包含了与所给筛选条件相匹配的对象
⑤exclude(条件)
它包含了与所给筛选条件不匹配的对象
⑥了不起的双下划线(__)之单表条件查询
# models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # # startswith,istartswith, endswith, iendswith, #----------------了不起的双下划线(__)之多表条件关联查询--------------- # 正向查找(条件) # 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").values('title') print(ret6) #注意 #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段 #一对多和多对多在这里用法没区别 # 反向查找(条件) #反向查找之一对多: ret8=models.Publisher.objects.filter(book__title='Python').values('name') print(ret8)#[{'name': '人大出版社'}] 注意,book__title中的book就是Publisher的关联表名 ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors') print(ret9)#[{'book__authors': 1}, {'book__authors': 2}] #反向查找之多对多: ret10=models.Author.objects.filter(book__title='Python').values('name') print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}] #注意 #正向查找的book__title中的book是表名Book #一对多和多对多在这里用法没区别
③一对多操作
class Book(models.Model): name=models.CharField(max_length=20) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") class Publish(models.Model): name=models.CharField(max_length=32) city=models.CharField(max_length=32) class Author(models.Model): name=models.CharField(max_length=32)
增(从表):
方式1:(推荐)
def addbook(req): Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish_id=2) return HttpResponse("ok")
方式2:
def addbook(req):
publish_obj=Publish.objects.filter(name="人民出版社")[0] Book.objects.create(name="linux运维",price=77,pub_date="2017-12-12",publish=publish_obj) return HttpResponse("ok")
查:
在从表通过外键查询主表的信息:
方式1:
def cha(req): book_obj=Book.objects.get(name="python") print(book_obj.publish) #Publish object print(type(book_obj.publish)) #<class 'app01.models.Publish'>
print(book_obj.publish.name) #输出主表的信息
print(book_obj.publish.city) return HttpResponse("ok")
方式2:
了不起的双下划线(__)之一对多条件查询
def cha(req): Publish.objects.filter(book__name="python").values("name") #这里book是类的名字 return HttpResponse("ok")
方式3:
了不起的双下划线(__)之一对多条件查询
def cha(req): Book.objects.filter(name="python").values("publish__name") #这里publish是类?外键字段?的名字。我觉得这里publish是外键的字段 return HttpResponse("ok")
在从表查询外键为X的所有数据:
方式1:
def cha(req): pub_obj=Publish.objects.filter(name="人民出版社")[0] ret=Book.objects.filter(publish=pub_obj).values("name","price") print(ret) return HttpResponse("ok")
方式2:
def cha(req): ret1=Publish.objects.filter(id=2).values("book_set")#这里book是类名,#从主表查询主表的某条数据在从表里的id:(如果没有的话返回None),也可以求这个QuerySet的长度来计算在从表里出现的次数 ret2=Publish.objects.filter(id=2).values("book_set__price")
print(ret1,ret2) return HttpResponse("ok")
方式3:
def cha(req): pub_obj=Publish.objects.filter(name="人民出版社")[0] print(pub_obj.book_set.all()) #<QuerySet [<Book:GO>,<Book:JAVA>]> #这里book是类名 print(type(pub_obj.book_set.all()) #<class 'django.db.models.query.QuerySet'> return HttpResponse("ok")
方式4:
了不起的双下划线(__)之一对多条件查询
def cha(req): Book.objects.filter(publish__name="人民出版社") #这里publish是外键的字段 return HttpResponse("ok")
当有多层级关系的时候:
④多对多操作
建立关系方式1:(推荐)
class Book(models.Model): name=models.CharField(max_length=20) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author")#这时候第三张表的名字是book_authors class Publish(models.Model): name=models.CharField(max_length=32) city=models.CharField(max_length=32) class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField(default=20)
查:
A和B是多对多关系,A表里有ManyToMany字段,在A表通过ManyToMany字段查询B表信息
方式1:
def cha(req): book_obj=Book.objects.get(id=3) print(book_obj.authors.all()) #<QuerySet [<Author object>,<Author:Author object>]> print(type(book_obj.authors.all()) #<class 'django.db.models.query.QuerySet'> return HttpResponse("ok")
方式2:
了不起的双下划线(__)之多对多条件查询
def cha(req): ret=Book.objects.filter(price=99).values("authors__name") print(ret) return HttpResponse("ok")
方式3:
从A表查询A表的某条数据在B表里的id:(如果没有的话返回None),也可以求这个QuerySet的长度来计算在B表里出现的次数
def cha(req): ret=Book.objects.filter(id=3).values("authors")
print(ret)
return HttpResponse("ok")
在B表查询A表的信息
方式1:
def cha(req): author_obj=Author.objects.get(id=2) author_obj.book_set.all() return HttpResponse("ok")
方式2:
了不起的双下划线(__)之多对多条件查询
def cha(req): ret=Book.objects.filter(authors__name="alex").values("name","price") print(ret) return HttpResponse("ok")
方式3:
从B表查询B表的某条数据在A表里的id:(如果没有的话返回None),也可以求这个QuerySet的长度来计算在A表里出现的次数
def cha(req): ret=Author.objects.filter(id=2).values("book_set")
#ret=Author.objects.filter(id=2).values("book_set__price")
print(ret)
return HttpResponse("ok")
增(第三张表):
def add(req):
方式1: book_obj=Book.objects.get(id=4) author_objs=Author.objects.all() book_obj.authors.add(*author_objs)
#book_obj.authors.add(1),这里如果添加的只添加id的时候不用写*号
#book_obj.authors.add([4,3])
#book_obj.authors.set([1,2,4,5]),book_id=4和author_id=1,2,4,5设置绑定关系(注:不是新增,而是更新成这个状态)
方式2:
author_obj=Author.objects.get(id=2)
book_objs=Book.objects.all()
author_obj.book_set.add(*book_objs)
#author_obj.book_set.add(1),这里如果添加的只添加id的时候不用写*号
#author_obj.book_set.add([4,3])
#author_obj.book_set.set([1,2,4,5]),author_id=2和book_id=1,2,4,5设置绑定关系(注:不是新增,而是更新成这个状态)
return HttpResponse("ok")
删(第三张表):
方法1:
def remove(req): book_obj=Book.objects.get(id=3) author_objs=Author.objects.all()#如果这个不是queryset,那么下面不用写*,参考上面的增 book_obj.authors.remove(*author_objs)
#book_obj.authors.remove(1)
#book_obj.authors.remove([4,3])
#book_obj.authors.clear()#删除book_id为3的所有数据
方法2:
def remove(req): book_obj=Book.objects.get(id=3) book_obj.authors.remove(2)#这个数字表示删除3对应的2,如果2不存在,则报错
=================================
建立关系方式2:
class Book(models.Model): name=models.CharField(max_length=20) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") class Publish(models.Model): name=models.CharField(max_length=32) city=models.CharField(max_length=32) class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField(default=20) class Book_Author(models.Model): book=models.ForeignKey("Book") author=models.ForeignKey("Author")
class Meta:
unique_together=[('u','t')]
增(第三张表):
def add(req): Book_Author.objects.create(book_id=2,author_id=3) return HttpResponse("ok")
查:
方式1:
def cha(req): obj=Book.objects.get(id=2) print(obj.book_author_set.all()[0].author) return HttpResponse("ok")
方式2:
了不起的双下划线(__)之多对多条件查询
通过Author表里的author__name="alex",查询Book表里的信息
def cha(req): ret=Book.objects.filter(book_author__author__name="alex").values("name","price") print(ret) return HttpResponse("ok")
=====================================
建立关系方式3:
class Book(models.Model): name=models.CharField(max_length=20) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") authors=models.ManyToManyField("Author",
through='Book_Author', #把Book_Author当做第三张表
through_fields=['book','author']) #在第三张表中把book和author当做关联字段 class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField(default=20)
class Book_Author(models.Model):
book=models.ForeignKey("Book")
book1=models.ForeignKey("Book")
author=models.ForeignKey("Author")
ctime=models.DateField()
class Meta:
unique_together=[('u','t')]
这么建立的话authors的add和set等方法不能用,
⑤多对多自关联
class User(models.Model): username=models.CharField(max_length=32,db_index=True) d=models.ManyToManyField('User',related_name='b')#自关联的时候一定要加related_name
数据库里生成user_d表
⑤ 聚合查询
aggregate(*args,**kwargs):
from django.db.models import Avg,Min,Sum,Max,Count >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35}
#改返回值里的名字 >>> Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} 如果你也想知道所有图书价格的最大值和最小值,可以这样查询: >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}
⑥分组查询
annotate(*args,**kwargs):
可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
(1)查询alex出的书总价格
(2)查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name
(3)查询各个出版社最便宜的书价是多少
============================
==========================
⑦F查询和Q查询
F,Q和普通的条件一起使用的时候F,Q应该放在前面
(1)给所有的书的价格提升10元
Book.objects.all().update(price=F("price")+10)
(2)筛选价格为89元,或者作者为jiongwen的书
ret=Book.objects.filter(Q(price=89)|Q(authors__name="jiongwen"))
(3)筛选价格非89元的书
ret=Book.objects.filter(~Q(price=89))
⑧QuerySet的惰性机制
(1)
解决方法:
ret=Book.objects.filter(name="python") for i in ret: print(i.price) Book.objects.all().update(price=200) ret=Book.objects.filter(name="python") for i in ret: print(i.price)
(2)QuerySet可以使用生成器
处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统 进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法 来获取数据,处理完数据就将其丢弃。 objs = Book.objects.all().iterator() # iterator()可以一次只从数据库获取少量数据,这样可以节省内存 for obj in objs: print(obj.name) #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了 for obj in objs: print(obj.name) #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使 用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
5.COOKIE和SESSION配合使用
把settings.py里的MIDDLEWARE改成MIDDLEWARE_CLASSES
def login(req): if req.method=='post': name=req.POST.get('user') pwd=req.POST.get('pwd') if name=="yuan" and pwd =="123": req.session['is_login']=True req.session['user'] = name return redirect('/index/') return render(req,'login.html') def index(req): if req.session.get("is_login",None): name=req.session.get("user") return render(req,'index.html',locals()) else: return redirect('login')
删除session:del request.session[key]
def logout(request): try: #删除is_login对应的value值 del request.session['is_login'] except KeyError: pass #点击注销之后,直接重定向回登录页面 return redirect('/login/')
设置session的保存时间(session默认在服务器端保存15天):
request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
6.Django请求生命周期
在views.py里
URL→函数→FBV
URL→类→CBV
①CBV
urls.py:
views.py:
7.Ajax
Ajax偷偷向后台发请求
1.下载引入jQuery 2.$.ajax({ url:"要提交的地址", type:'提交方式/GET/POST', data:{'username':'root','password':'123'}, success:function(arg){ //回调函数,我向后台发送了请求,后台给我返回了结果的时候自动执行 arg是服务端返回的数据 } })
2个简单的ajax功能:
urls.py
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'ajax1$', views.ajax1), url(r'ajax2$', views.ajax2), url(r'ajax3$', views.ajax3), ]
views.py
def ajax1(req): return render(req,'ajax1.html') def ajax2(req): user=req.GET.get('username') pwd=req.GET.get('password') return HttpResponse('ok') def ajax3(req): v1=req.POST.get('v1') v2=req.POST.get('v2') print(v1) try: v3=int(v1)+int(v2) except Exception as e: v3="输入格式错误" return HttpResponse(v3)
html:
<body> <div> <input placeholder="用户名" type="text" id="username"> <input placeholder="密码" type="password" id="password"> <div class="btn" onclick="submitForm();">提交</div> </div> <p></p> <div> <input placeholder="数字" type="text" id="i1"> + <input placeholder="数字" type="text" id="i2"> <div class="btn" onclick="addForm();">等于</div> <input placeholder="数字" type="text" id="i3"> </div> <script> function submitForm() { var u=$('#username').val(); var p=$('#password').val(); $.ajax({ url:'/ajax2', type:'GET', data:{username:u,password:p}, success:function(arg){ console.log(arg); } }) } function addForm() { var v1=$('#i1').val(); var v2=$('#i2').val(); $.ajax({ url:'/ajax3', type:'POST', data:{'v1':v1,'v2':v2}, success:function(arg){ $('#i3').val(arg) } }) } </script> </body>
更高级一点的:
点Ajax删除的时候不刷新页面删除那一条数据
html:
function removeStudent(ths) {
var nid=$(ths).parent().attr('nid');
$.ajax({
url:'/ajax4',
type:'GET',
data:{nid:nid}
success:function (arg) {
if(arg == '成功'){
$(ths).parent().parent().remove()
}else{
alert(arg)
}
}
})
}
views.py
def ajax4(req): nid=req.GET.get('nid') msg='成功' try: Student.objects.filter(id=nid).delete() except Exception as e: msg=str(e) return HttpResponse(msg)
==============================================
traditional:
ajax里data的v是列表的时候,要用traditional
================================================
ajax里data的v转换成json字符串:
===============================================
datatype:json
把服务器返回的数据当做json格式来接受(把后端传过来的json字符串自动转换成jQuery对象)
===============================================
ajax - serialize() 方法:
只能用在form表单里:
ajax向后台传form表单里的内容的时候可以将form表 单里的name和value值组合在一个key里传输
html:
<form action="/test73" method="get"> First name: <input type="text" name="FirstName" value="账号" /><br /> Last name: <input type="text" name="LastName" value="密码"/><br /> select: <select name="sel" id="ss"> <option value="1">a</option> <option value="2">b</option> <option value="3">c</option> </select> </form> <button class="bt">序列化表单值</button>
jquery:
<script> $(function () { test(); }); function test() { $('.bt').click(function () { t=$("form").serialize(); $.ajax({ url:'/test73', type:'GET', ①data:{t:t},
②data:$("form").serialize(), success:function(arg){ console.log(arg); } }) }) } </script>
后台:
def test73(req): ①t=req.GET.get('t')
①tt=req.GET.get('FirstName')
①print(t,tt)
②t=req.GET.get('t')
②tt=req.GET.get('FirstName')
②print(t,tt) //None 23
return HttpResponse('73') def test731(req): return render(req,'test0703.html')
结果:
FirstName=23&LastName=111&sel=3 None
=========================================
ajax上传文件(jQuery):
html:
<input type="file" id="img"> <a class="btn" οnclick="AjaxSubmit6();">ss</a>
script:
<script> function AjaxSubmit6() { var data=new FormData(); data.append('k1','v1'); data.append('k2','v2'); data.append('k3',document.getElementById('img').files[0]);//获取文件 $.ajax({ url:'/ajax1', type:'POST', data:data, processData:false,//tell jQuery not to process the data contentType:false,//tell jQuery not to set contentType success:function (arg) { console.log(arg) } }) } </script>
jsonp:有scr的都不遵循同源策略
html:
<input type='button' value='发送2' onclick='submitJsonp2();'>
script:
<script> function submitJsonp2() { var tag=document.createElement('script'); tag.src='http://127.0.0.1:9000/xiaokai.html'; //在地址后面加?callback=abc的话意思就是后台让我执行的那个函数名本来是fuck,把那个函数名变成abc document.head.appendChild(tag); document.head.removeChild(tag); } //上面的代码可以通过以下的jQuery来简写 function submitJsonp2() { $.ajax({ url:'http://127.0.0.1:9000/xiaokai.html', type:'GET', dataType:'jsonp', //jsonp只能是get
//jsonp:'callback', 后台让我执行的那个函数名本来是fuck,把那个函数名变成abc
//jsonpCallback:'abc', }) } function fuck(arg) { //function abc(arg) console.log(arg); } </script>
另一个域的后台:
def xiaokai(req):
return HttpResponse('fuck("我要上小云");')//告诉前端,我要执行这个函数
//name=req.GET.get('callback')
//return HttpResponse('%s("我要上小云");'%(name))
8.bootstrap制作模态对话框
以下是上面模态对话框的代码
下半区的内容是需要用到的,其中用id='myModal'来操作,使用里面的方法
JS部分:
$(function () { bindEvent(); submitForm(); addForm(); }); function bindEvent() { $('#addBtn1').click(function () { $('#myModal').modal('show'); #$('#myModal').modal('hide');是隐藏 }) } function submitForm() { var u=$('#username').val(); var p=$('#password').val(); $.ajax({ url:'/ajax2', type:'GET', data:{username:u,password:p}, success:function(arg){ console.log(arg); } }) } function addForm() { var v1=$('#i1').val(); var v2=$('#i2').val(); $.ajax({ url:'/ajax3', type:'POST', data:{'v1':v1,'v2':v2}, success:function(arg){ $('#i3').val(arg) } }) }
9.分页
分页基础知识:
HTML:
<body> <ul> {% for row in user_list %} <li>{{ row.name }}-{{ row.age }}</li> {% endfor %} </ul> <a href="/index?p={{ prev_pager }}">上一页</a> <a href="/index?p={{ next_pager }}">下一页</a> </body>
后台:
def index(req): per_page_count=10 current_page=req.GET.get('p')#http://127.0.0.1:8000/index?p=1 current_page=int(current_page) #p=1 #0,10 0-9 #p=2 #10,20 10-19 star=(current_page-1)*per_page_count end=current_page*per_page_count data=USER_LIST[star:end] prev_pager=current_page-1 next_pager=current_page+1 return render(req,'test07032.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager})
效果:
Django内置分页及扩展:
在views.py里先引入这个from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
HTML:
<body> <ul> {% for row in posts.object_list %} <li> {{ row.name }}-{{ row.age }} </li> {% endfor %} </ul> {% if posts.has_previous %} <a href="/index1?p={{ posts.previous_page_number }}">上一页</a> {% else %} #这一部分的作用是第一页的时候也有上一页,但是点了没反应 <a href="#">上一页</a> {% endif %} {% for i in posts.paginator.pager_num_range %} {% if i == posts.number %} <a style=" font-size: 30px;" href="/index1?p={{ i }}">{{ i }}</a> {% else %} <a href="/index1?p={{ i }}">{{ i }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="/index1?p={{ posts.next_page_number }}">下一页</a> {% endif %} <span> 当前页:{{ posts.number }},总页数:{{ posts.paginator.num_pages }} </span> </body>
后台:
USER_LIST=[] for i in range(1,999): temp={'name':'root'+str(i),'age':i} USER_LIST.append(temp) class CustomPaginator(Paginator): def __init__(self,current_page,per_pager_num,*args,**kwargs): self.current_page=int(current_page)#当前页 self.per_page_num=int(per_pager_num)#最多显示的页码数量 super(CustomPaginator,self).__init__(*args,**kwargs) def pager_num_range(self): if self.num_pages<self.per_page_num: return range(1,self.num_pages+1) part=int(self.per_page_num/2) if self.current_page<=part: return range(1,self.per_page_num+1) if (self.current_page+part)>self.num_pages: return range(self.num_pages-self.per_page_num+1,self.num_pages+1) return range(self.current_page-part,self.current_page+part+1) def index1(req): if req.GET.get('p'): current_page = req.GET.get('p') else: current_page=1 paginator=CustomPaginator(current_page,11,USER_LIST,10)#所有数据(如果从数据库取的话可以用Queryset),每页显示10个) # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象(是否具有下一页,是否具有上一页) try: posts = paginator.page(current_page)#这里的posts就是page对象 # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表 # number 当前页 # paginator paginator对象 except PageNotAnInteger: posts = paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_pages)
效果:
自定义分页组件:
HTML:
<body> <ul> {% for row in data %} <li> {{ row.name }}-{{ row.age }} </li> {% endfor %} </ul> {% for i in page_obj.pager_num_range %} <a href="/index2?p={{ i }}">{{ i }}</a> {% endfor %} <hr> {{ page_obj.page_str|safe }} </body>
后台:
USER_LIST=[] for i in range(1,999): temp={'name':'root'+str(i),'age':i} USER_LIST.append(temp) class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=30,maxPageNum=7): self.total_count=totalCount #数据总个数 try: v=int(currentPage) if v<=0: v=1 self.current_page=v #当前页 except Exception as e: self.current_page =1 self.per_page_item_num=perPageItemNum #每页显示的行数 self.max_page_num=maxPageNum #最多显示页码 def start(self): return (self.current_page-1)*self.per_page_item_num def end(self): return self.current_page*self.per_page_item_num def num_pages(self): #总页数 a,b=divmod(self.total_count,self.per_page_item_num) if b==0: return a return a+1 def pager_num_range(self): if self.num_pages() <self.max_page_num: return range(1,self.num_pages()+1) part=int(self.max_page_num/2) if self.current_page<=part: return range(1,self.max_page_num+1) if (self.current_page+part)>self.num_pages(): return range(self.num_pages()-self.max_page_num+1,self.num_pages()+1) return range(self.current_page-part,self.current_page+part+1) def page_str(self): page_list=[] first="<a href='/index2?p=1'>首页</a>" page_list.append(first) if self.current_page==1: prev="<a href='#'>上一页</a>" else: prev = "<a href='/index2?p=%s'>上一页</a>"%(self.current_page-1) page_list.append(prev) for i in self.pager_num_range(): if i == self.current_page: temp="<a style='font-size:30px;' href='/index2?p=%s'>%s</a>"%(i,i) else: temp = "<a href='/index2?p=%s'>%s</a>" % (i,i) page_list.append(temp) if self.current_page==self.num_pages(): nex="<a href='#'>下一页</a>" else: nex="<a href='/index2?p=%s'>下一页</a>"%(self.current_page+1) page_list.append(nex) last = "<a href='/index2?p=%s'>尾页</a>"%(self.num_pages()) page_list.append(last) return ''.join(page_list) def index2(req): if req.GET.get('p'): current_page=req.GET.get('p') else: current_page=1 page_obj=Pagination(998,current_page) data_list=USER_LIST[page_obj.start():page_obj.end()] return render(req,'index2.html',{'data':data_list,"page_obj":page_obj})
效果:
10.DjangoForm组件
http://www.cnblogs.com/wupeiqi/articles/6144178.html
功能:对用户请求的验证
生成HTML代码
html:
<body> <form action="/index3" method="POST" novalidate><!--novalidate:浏览器不会对表单进行验证--> {%csrf_token%} <p>user:{{ obj.user }}{{ obj.errors.user.0 }}{{ obj.user.help_text }}如果在这模板语言中写成user.0的话只取第一个错误,前面的黑点也会消失</p> <p>password:{{ obj.pwd.label }}{{ obj.pwd }}{{ obj.errors.pwd }}obj.pwd自动创建input标签,而且submit提交的时候条件不符合的话以前输入的值不会消失</p> <p>email:<input type="text" name="email">{{ obj.errors.email }}</p> <p>age:<input type="text" name="age">{{ obj.errors.age }}</p> <p><input type="submit" value="submit提交"></p> </form> <p><button class="bt">ajax提交</button></p> <script> $(function () { test(); }); function test() { $('.bt').click(function () { $.ajax({ url:'/index3', type:'GET', data:$("form").serialize(), success:function(arg){ console.log(arg); } }) }) } </script> </body>
后台:
from django import forms from django.forms import fields class F1Form(forms.Form):#下面前面的变量是前端里的name值 user=fields.CharField( max_length=18, min_length=6, initial='12', # 输入框里的默认值 help_text='xxx',#帮助信息(在标签旁边显示) #show_hidden_initial=True, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) #disabled=True, 不可以编辑 required=True, error_messages={ 'required':'用户不能为空', 'max_length':'最大长度不能超过18' })#最大/小长度,不能为空,后面的字典可以自定制错误信息 pwd=fields.CharField(min_length=8,required=True,label='密码')#如果在前端写了label之后这里不写label的话默认值是这个常量的名字(pwd) age=fields.IntegerField( required=True, help_text='asdf', max_value=123,#最大值 min_value=12,#最小值 error_messages={ 'required': '年龄不能为空', 'invalid':'必须为数字',#格式错误的时候都用invalid } ) email=fields.EmailField(required=True) def index3(req): if req.method=="GET": if req.GET.get('user'): obj = F1Form(req.GET) if obj.is_valid(): # 是否全部验证成功 print('验证成功', obj.cleaned_data) # 用户提交的数据 else: print('验证失败', obj.errors) return HttpResponse("ok") else: obj = F1Form()#如果这里F1Form({'user':123})这样的话生成的input框user会有默认值123 return render(req,'index3.html',{'obj':obj}) if req.method=='POST': obj=F1Form(req.POST) if obj.is_valid(): #是否全部验证成功 print('验证成功',obj.cleaned_data)#用户提交的数据 return redirect('https://www.baidu.com/') else: print('验证失败',obj.errors) return render(req,'index3.html',{'obj':obj})
11.rest framework
①django从数据库取数据后往前端返回json数据
上面的代码可以简化(推荐)
②使用django rest framework
INSTALLED_APPS = ( ... 'rest_framework',
'django_filters', )
urlpatterns = [ ... url(r'^api-auth/', include('rest_framework.urls')) ]
③使用django rest framework的文档功能
④后端收到请求后往前端发送数据
serializers.py:
以上的可以简写成这样:
(一)选特定的字段
(二)选所有字段
(三)把一对多的从表信息传到前端的时候外键传过去的话前端外键显示的是id号,如果在前端想把外键id号变成主表的信息的话:
views.py:
⑤ serializers.py把前端传来的数据添加到数据库上
serializers.py:
views.py:
⑥前端向后端get请求后返回数据(GenericView方式)
views.py:
serializers.py:
⑦分页
views.py:
⑧viewsets和router
views.py:
serializers.py:
urls:
⑨总结以上内容
⑩drf的request和response
(一)request
request.data:后台收到post请求后从这里取数据
request.query_params:后台收到get请求后从这里取数据
request.parsers:后台收到请求后不管是什么类型的请求,都可以从这里取数据
(二)responses
data:
status:
template_name:
headers:
content_type:
⑪drf的过滤
下面的设置用过滤,搜索,排序的时候都要做
用法:
Ⅰ.过滤某个字段里具体的值(精确)
views.py:
Ⅱ.模糊过滤
views.py:
filters:
12.drf的搜索
view.py:
13.drf的排序
view.py:
14.商品类别数据接口
在所有数据当中获取某个数据
15.JWT
settings.py:
urls.py:
自定义用户认证:
settings: