Django第二天
Django第二天
Django流程
(1)设计URL
#urls.py #简单分配 urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^host_list/',views.host_list), url(r'^add_host/',views.add_host), url(r'^del_host/',views.del_host), url(r'^edit_host/',views.edit_host), ] 上面的代码是整个django项目的路由入口。 r'^host_list/',views.host_list ==>表示的是访问/host_list/时调用视图中的host_list函数。 ==> views.host_list(request) #分组 urlpatterns = [ url(r'^host_list/(\d+)',views.test_list), #此时路径传入了数字 ] def test_list(requests,res): #此时视图函数需要接收这个参数 return HttpResponse(res) #有名分组 urlpatterns = [ url(r'^host_list/(?P<year>\d+)/(?P<moth>[0-9]{2})/',views.test_list), ] def test_list(requests,year,moth): #视图接收时需要接收这两个参数 return HttpResponse('%s-%s' %(year,moth)) #分发 分发指的就是将url分发到项目的应用中 #项目的url urlpatterns = [ url(r'^app01/',include('app01.urls')), #指如果是app01的路径指向app01的urls。 ] #app01的路由 urlpatterns = [ url(r'^list/(?P<year>\d+)/(?P<moth>[0-9]{2})/$',test_list), ] def test_list(requests,year,moth): return HttpResponse('%s-%s' %(year,moth)) #url的反向解析 urlpatterns = [ url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'), #name设置别名 ] #在模板中引用 <a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> 如果以后产品需求我们的url进行变更时,那么在模板中的url会自动变更。这样的话我们在进行修改的时候就有就不用再考虑模班中的引用。 #变个玩法 urlpatterns = [ url(r'^list/(\d+)/$',test_list,name="abc"), #设置别名 ] def test_list(requests,res): #接入参数 return render(requests,'test.html',{"res":res}) #将参数传入模板 <a href="{% url 'abc' res %}"> 2012</a> #接入参数 当url有分组的时候,在接入参数的位置需要默认值{% url 'abc' res %},如果没有分组情况,那么可以不用默认参数
需要注意的是:Django的路由匹配是从上往下,依次匹配,如果匹配到了不在继续往下匹配。url的参数中如果带有?d=11类似这种的参数是可以通过GET方法获取的。但是参数写在路径中是无法通过GET获取的,只能通过分组的方式。视图获取的参数都是string。
Django的视图
request对象
1 #request对象的常用值 2 path_info 返回用户访问url,不包括域名 3 method 请求中使用的HTTP方法的字符串表示,全大写表示。 4 GET 包含所有HTTP GET参数的类字典对象 5 POST 包含所有HTTP POST参数的类字典对象 6 body 请求体,byte类型 request.POST的数据就是从body里面提取到的
response对象
1 内部传入一个字符串参数,返回给浏览器。 2 def index(request): 3 # 业务逻辑代码 4 return HttpResponse("OK")
render对象
除request参数外还接受一个待渲染的模板文件和一个保存具体数据的字典参数。 将数据填充进模板文件,最后把结果返回给浏览器。(类似于我们上面用到的jinja2) def index(request): # 业务逻辑代码 return render(request, "index.html", {"name": "alex", "hobby": ["烫头", "泡吧"]})
redirect对象
接受一个URL参数,表示跳转到指定的URL。 def index(request): # 业务逻辑代码 return redirect("/home/")
Django模板
模板的渲染方法有:渲染变量 {{ }},渲染标签 {% %}。
渲染变量
#视图函数传递参数 def test_list(requests): res = {"name":'abc',"age":123} return render(requests,'test.html',{"res":res}) <p>{{ res.name }}:{{ res.age }}</p> #模板中深度查询句点符。 <p>{{ res.name }}:{{ res.age|add:100 }}</p> #模板过滤器让age添加100 <p>{{ now|date:"Y-m-d" }}</p> #让时间按照指定格式显示 <p>{{ file_size|filesizeformat }}</p> #将值格式化为一个 “人类可读的” 文件尺寸 <p>{{ content|truncatechars:12 }}</p> #如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 <p>{{ content|truncatewords:2 }}</p> #显示1个字符其他用……表示 <p>{{ s|safe }}</p> #告诉django s字符不需要进行转义 <p>{{ value|default:"nothing" }}</p> #如果一个变量是false或者为空,使用给定的默认值,否则,使用变量的值。
渲染标签
#视图函数传递参数 def test_list(requests): res = {"name":'shier1',"age":12} res1 = {"name":'shier2',"age":13} return render(requests,'test.html',{"res":[res,res1]}) #模板 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> {% for re in res %} {% if re.age == 12 %} <p>{{ re.name }}:{{ re.age }}</p> {% endif %} {% endfor %} </body> </html> </html>
自定义过滤器
1 #1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag. 2 #2、在app中创建templatetags模块(模块名只能是templatetags) 3 #3、创建任意 .py 文件,如:my_tags.py 4 5 #my_tag.py 6 from django import template 7 from django.utils.safestring import mark_safe 8 9 register = template.Library() 10 11 @register.filter 12 def multi_filter(x,y): 13 return x * y 14 15 @register.simple_tag 16 def my_input(id,arg): 17 result = "<input type='text' id='%s' class='%s' />" %(id,arg) 18 return mark_safe(result) 19 20 #test.html 21 {% load my_tags %} 22 <!DOCTYPE html> 23 <html lang="en"> 24 <head> 25 <meta charset="UTF-8"> 26 <title>test</title> 27 </head> 28 <body> 29 {% for re in res %} 30 {% if re.age == 12 %} 31 <p>{{ re.name }}:{{ re.age|multi_filter:50 }}</p> 32 {% endif %} 33 {% my_input 2 5 %} 34 {% endfor %} 35 36 </body> 37 </html> 38 39 #在模板中调用自定义过滤器 40 {% for re in res %} 41 {% if re.age == 12 %} 42 <p>{{ re.name }}:{{ re.age|multi_filter:50 }}</p> #调用自定义过滤器,最多传入2个参数 43 {% endif %} 44 {% endfor %} 45 46 #自定义标签 47 {% simple_tag_multi 2 5 %} 参数不限,但不能放在if for语句中 48 {% simple_tag_multi num 5 %} 49 #注意的事:filter可以用if条件,simple_tag_multi不可以 50 {% if num|filter_multi:30 > 100 %} 51 {{ num|filter_multi:30 }} 52 {% endif %}
在模板中如果有from表单的提交时,第一次发起提交的时候回出现403的情况,此时需要在模板的from表单下中添加 {% csrftoken %}防止csrf攻击。
Django的模型
Django的ORM指的是Object Relational Mapping(关系对象映射)
在模型和表的对应关系:
类名 ----- 表名 类属性 ----- 表字段 类实例对象 ----- 表记录 django中的表的关系: 当一对多关系的时候:可以创建关联字段 当多对多关系:创建关联表
创建模型
比如我们要写一个图书管理系统,那么就会涉及的对象有:作者,出版社,书。
作者有姓名,年龄;出版社有名称,地址;书有出版日期,该书的作者。
#书表 class Bool(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=6,decimal_places=2) create_time = models.DateField() memo = models.CharField(max_length=32,default="") #建立和图书和出版社的关系(一对多,外键应该建立在多的一方) publish = models.ForeignKey(to="Publish",default=1) #建立图书和作者的关系(多对多的关系,这个可以建在任意一方,此时的第三张管理表会自动创建,不在需要手动创建) author = models.ManyToManyField("Author") def __str__(self): return self.title #出版社表 class Publish(models.Model): name = models.CharField(max_length=32) email = models.CharField(max_length=32) #作者表 class Author(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name
设置logging可以查看django后台执行的sql语句
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, }, } #将这个设置添加到setting文件中
注意事项:
1、 表的名称myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称
2、id 字段是自动添加的
3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
4、这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。
5、定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。
6、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
数据迁移报错:django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: app01
因为setting设置了多次app01项目。去掉一个即可
添加表记录
# 方式1: # obj新添加记录对象 obj=Book.objects.create(title="python") # 方式2: obj=Book(title="java") obj.save()
查询方法
1 <1> all(): 查询所有结果,返回QuerySet对象. 2 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象,返回QuerySet对象. 3 <3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,返回具体的对象 4 如果符合筛选条件的对象超过一个或者没有都会抛出错误。 5 <5> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象,返回QuerySet对象 6 <4> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列,返回QuerySet对象 7 <9> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列,返回QuerySet对象 8 <6> order_by(*field): 对查询结果排序,返回QuerySet对象 9 <7> reverse(): 对查询结果反向排序,返回QuerySet对象 10 <8> distinct(): 从返回结果中剔除重复纪录,返回QuerySet对象 11 <10> count(): 返回数据库中匹配查询(QuerySet)的对象数量 12 <11> first(): 返回第一条记录,返回具体对象 13 <12> last(): 返回最后一条记录,返回具体对象 14 <13> exists(): 如果QuerySet包含数据,就返回True,否则返回False 15 16 #模糊查询 17 18 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 19 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 20 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in 21 models.Tb1.objects.filter(name__contains="ven") 22 models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 23 models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and 24 startswith,istartswith, endswith, iendswith
删除记录
Book.objects.filter(price=123,title="python").delete()
更新记录
Book.objects.filter(price=123,title="python").update(title="python123")