django详细概念
一:model
一:modle的choices的用法:
1 from django.db import models
2
3 class Person(models.Model):
4 SHIRT_SIZES = (
5 ('S', 'Small'),
6 ('M', 'Medium'),
7 ('L', 'Large'),
8 )
9 name = models.CharField(max_length=60)
10 shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
数据库中存储的是S M L如何获取对应的small medium large:
1 >>> p = Person(name="Fred Flintstone", shirt_size="L") 2 >>> p.save() 3 >>> p.shirt_size 4 'L' 5 >>> p.get_shirt_size_display() 6 'Large'
需要注意的:
其中SHIRT_SIZES是可迭代的对象(元组或者列表。)即:
1 SHIRT_SIZES = (
2 ('S', 'Small'),
3 ('M', 'Medium'),
4 ('L', 'Large'),
5 )
6 or
7 SHIRT_SIZES = [
8 ('S', 'Small'),
9 ('M', 'Medium'),
10 ('L', 'Large'),
11 ]
还有数据库中实际存储的是字符类型: S L M,如上例子存储数据库里的字段和select标签显示的字段类型是一样的。需要注意实际存的是字段类型要和实际数据库存储的类型是一致的。而不是select标签的数据类型。
二:主键
默认django给咱们创建列名为id自增的主键,主键是只读字段,如果你想修改该字段的话,给当前的行对象的主键重新赋值的话,结果会创建一个新的对象,主键是你想赋值的值。其他字段和你想赋值的主键对应的行。
1 from django.shortcuts import render,HttpResponse
2 from modle_1 import models
3 # Create your views here.
4
5 def get_a(request):
6 ret=models.person.objects.create(name='tt',age=111)
7 print(ret)
8 ret.name='mm'
9 ret.save()
10 res=models.person.objects.all().values_list('name')
11 print(res)
12 return HttpResponse('ok')
1 from django.db import models 2 3 # Create your models here. 4 class person(models.Model): 5 name=models.CharField(max_length=32,primary_key=True) 6 age=models.IntegerField()
数据库:

在django中。model必须有一个主键,如果你不自定义一个主键的话,django会自动给你创建一个自增的id,如果你想自定义自增的字段的话,可以用:
1 id = models.AutoField(primary_key=True)
使用AutoField类似于sqlalchemy中autoincrement=true的选项。来保证一个自增的主键列。
三:表关系(manytoon manytomany onetoone)
1、在多对一的情况下,可以和其他表进行关联也可以和自身进行关联(比如多级评论。)
2、manytomany的情况下,也可以对自身进行manytomany(As with ForeignKey, you can also create recursive relationships (an object with a many-to-many relationship to itself) and relationships to models not yet defined.)这种情况目前没有例子。
对于django的url配置理解
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^home/', views.home), 4 ]
a:为什么url中:url(r'^admin/', admin.site.urls),url前面没有/,django解释:
Django在检查URL模式前,移除每一个申请的URL开头的斜杠(/)。 这意味着我们为/hello/写URL模式不用包含斜杠(/)。
b:如果我们域名:www.django.com
如果我们在url.py文件进行定义如下:
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^home/', views.home), 4 url(r'^home/$', views.home), 5 url(r'home/$', views.home), 6 ]
如上三个home,都有什么含义呢?
首先我们来说url(r'^home/$', views.home)他是表示以home开头和结尾的url 即完全匹配:http://www.django.com/home/的url。
url(r'^home/', views.home)
1 from django.conf.urls import url 2 from django.contrib import admin 3 from testurl import views 4 urlpatterns = [ 5 url(r'^admin/', admin.site.urls), 6 url(r'^home/', views.home1), 7 url(r'^home/$', views.home2), 8 url(r'home/$', views.home3), 9 ]
view.py:
1 from django.shortcuts import render,HttpResponse
2
3 # Create your views here.
4 def home1(request):
5 return HttpResponse('^home/')
6 def home2(request):
7 return HttpResponse('^home/$')
8 def home3(request):
9 return HttpResponse('home/$')
首先我们访问: http://127.0.0.1:8000/foor/home/

我们访问:http://127.0.0.1:8000/home/
django 从上到下匹配,匹配到url之后就不会继续匹配。因为如上3个url都包含:http://127.0.0.1:8000/home/,所以谁在上面,就匹配那个。

那我们访问:http://127.0.0.1:8000/home/foor/

这个是时候,你会疑问 如果我们用严格匹配的方式:url(r'^home/$', views.home),我们使用:http://127.0.0.1:8000/home 访问的话,会出现什么呢?

在django中:
你可能会问:如果有人申请访问/hello(尾部没有斜杠/)会怎样。 因为我们的URL模式要求尾部有一个斜杠(/),那个申请URL将不匹配。 然而,默认地,任何不匹配或尾部没有斜杠(/)的申请URL,
将被重定向至尾部包含斜杠的相同字眼的URL。 (这是受配置文件setting中APPEND_SLASH项控制的)
所以我们建议我们的url一般设置成^path/$严格形式。
网站根目录设置参考:
1 from mysite.views import hello, my_homepage_view
2
3 urlpatterns = patterns('',
4 ('^$', my_homepage_view),
5 # ...
6 )
当我们请求/home/的时候,整个流程:
-
进来的请求转入/home/.
-
Django通过在ROOT_URLCONF配置来决定根URLconf.
-
Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目。
-
如果找到匹配,将调用相应的视图函数
-
视图函数返回一个HttpResponse
-
Django转换HttpResponse为一个适合的HTTP response, 以Web page显示出来
时区的设置,默认是‘美国/芝加哥'在seting中。根据需求进行修改。
如果请求URL是/time/plus/3/,那么offset将会是3 ,请注意:捕获值永远都是字符串(string)类型,而不会是整数(integer)类型,即使这个字符串全由数字构成(如:“21”)
1 from django.http import Http404, HttpResponse 2 import datetime 3 4 def hours_ahead(request, offset): 5 try: 6 offset = int(offset) 7 except ValueError: 8 raise Http404() 9 dt = datetime.datetime.now() + datetime.timedelta(hours=offset) 10 html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) 11 return HttpResponse(html)
django的模板语言
对于django的模板系统,实际上通过template类、context类、以及template类中的render方法,对html文档进行渲染。
1 Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32
2 Django 1.10
3 >>> from django.template import Template, Context
4 >>> import datetime
5 >>> d = datetime.date(1993, 5, 2)
6 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')#创建模板语言
7 >>> c = Context({'date': d})#contex函数 contex的对象可以理解成一个字典。
8 >>> t.render(c)
可以把contex的实例当做一个字典,可以对这个字段进行增删改查。
1 >>> c['dd']=22
2 >>> c
3 [{'False': False, 'True': True, 'None': None}, {'dd': 22, 'date': datetime.date(1993, 5, 2)}]
4 >>> del c['dd']
5 >>> c
6 [{'False': False, 'True': True, 'None': None}, {'date': datetime.date(1993, 5, 2)}]
因为他的父类中含有__setitem__ __getitem__ __delitiem__方法:
1 def __setitem__(self, key, value): 2 "Set a variable in the current context" 3 self.dicts[-1][key] = value 4 5 def __getitem__(self, key): 6 "Get a variable's value, starting at the current context and going upward" 7 for d in reversed(self.dicts): 8 if key in d: 9 return d[key] 10 raise KeyError(key) 11 12 def __delitem__(self, key): 13 "Delete a variable from the current context" 14 del self.dicts[-1][key]
上面代码需要运行在django shell中运行,否则会报一些django环境设置问题。避免不必要的麻烦。
总的来说:先通过Template类来创建一个模板,然后通过给类Context类传入值,这个值必须是字典,然后通过Template实例来调用render方法,将Conntext实例的值出入模板语言中!
在调用jina2的模板语言的时候,在模板中引用变量的时候,通过.可以调用相应的字段,当一列表的时候,也是通过.调用列表中的值,比如:{{item.1}},需要注意的列表的索引不能使用负数,如果使用负数的话,会引发`` TemplateSyntaxError``。
句点查找可以多级深度嵌套。 例如在下面这个例子中 {{person.name.upper}} 会转换成字典类型查找( person['name'] ) 然后是方法调用( upper() ):
对于在模板语言中调用python 方法。模板语言中可以调用一些方法,前提这个方法没有参数要求,否则会报错,调用的时候不需要加括号!
1 >>> from django.template import Template, Context
2 >>> person = {'name': 'Sally', 'age': '43'}
3 >>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')
4 >>> c = Context({'person': person})
5 >>> t.render(c)
6 u'SALLY is 43 years old.'
注意:
- 默认情况下,在文档加载的时候,在模板里的方法和变量自动执行,如果你想不执行的话,可以使用如下参数来保证文档加载完之后不被执行。必须设置该方法的 alters_data 函数属性:
1 def delete(self): 2 # Delete the account 3 delete.alters_data = True
模板系统不会执行任何以该方式进行标记的方法。 接上面的例子,如果模板文件里包含了 {{ account.delete }} ,对象又具有 delete()方法,而且delete() 有alters_data=True这个属性,
那么在模板载入时, delete()方法将不会被执行。 它将静静地错误退出。
当传递到前端变量为空字符串的时候,在django模板语言中,将该部分的变量不做前端‘显示’处理。
对于句点,有以下应用场景:
-
字典类型查找 (比如 foo["bar"] )
-
属性查找 (比如 foo.bar )
-
方法调用 (比如 foo.bar() )
-
列表类型索引查找 (比如 foo[bar] )
标签:
- if/else
1 {% if expression %}
2 <html标签1>
3 {%else %}
4 <html标签2>
5 {%endif%}
其中{%else%}是可选部分。
当if中的表达式满足条件,将显示html1的内容。
否则显示html2标签
在模板语言中的bool为假和python是一样的。
同样:if标签内支持 and、or、not等关键字。
1 {% if athlete_list and coach_list %}
2 Both athletes and coaches are available.
3 {% endif %}
4
5 {% if not athlete_list %}
6 There are no athletes.
7 {% endif %}
8
9 {% if athlete_list or coach_list %}
10 There are some athletes or some coaches.
11 {% endif %}
12
13 {% if not athlete_list or coach_list %}
14 There are no athletes or there are some coaches.
15 {% endif %}
16
17 {% if athlete_list and not coach_list %}
18 There are some athletes and absolutely no coaches.
19 {% endif %}
但是不支持:and和or一起使用,因为在语义上比较模糊。如下是语法错误的。
1 {% if athlete_list and coach_list or cheerleader_list %}
- for标签
形式:
1 {%for i in item%}
2 i.xxx
3 {%empty%}
4 'there is empy content!'
5 {%endfor%}
在for循环迭代后台传过来的列表或者元组的时候,如果列表和元组为空的时候,可以用{%empty%}标签来显示当迭代的对象为空的时候。
1 {% for athlete in athlete_list %}
2 <p>{{ athlete.name }}</p>
3 {% empty %}
4 <p>There are no athletes. Only computer programmers.</p>
5 {% endfor %}
在for标签中有个forloop变量,他有一些提示循环进度的信息。forloop.counter当前循环次数默认是从1开始:
1 <body>
2 <p>
3 {% for i in render %}
4 {{ forloop.counter }} {{ i }}<br>
5 {% endfor %}
6 </p>
7 </body>
1 def tem(request):
2 rend_list=['a','b']
3 return render(request,'1.html',{'render':rend_list})

也可以从0开始,需要使用forloop.counter0
1 <p>
2 {% for i in render %}
3 {{ forloop.counter0 }} {{ i }}<br>
4 {% endfor %}
5 </p>
6 </body>

forloop.revcounter表示剩余没有循环的元素。
1 <p>
2 {% for i in render %}
3 {{ forloop.revcounter }} {{ i }}<br>
4 {% endfor %}
5 </p>
6 </body>

当然也有forloop.revcounter0

其中比较中重要是第一次进行迭代的时候,即第一循环的时候和最后一次循环的时候,这2个使用的场景比较多。
forloop.first 返回的布尔值。一般需要放在if标签内
1 <p>
2 {% for i in render %}
3 {% if forloop.first %} <h1>{{ i }}</h1>
4 {% else %}
5 {{ i }}
6 {% endif %}
7 {% endfor %}
8 </p>

forloop.last 循环最后一次,返回也是布尔值
1 <p>
2 {% for i in render %}
3 {% if forloop.last %} <h1>{{ i }}</h1>
4 {% else %}
5 {{ i }}
6 {% endif %}
7 {% endfor %}
8 </p>

forloop.parentloop 是一个指向当前循环的上一级循环的 forloop 对象的引用(在嵌套循环的情况下)。
1 <p>
2 {% for i,j in render.items %}
3 {% for k in j %}
4 {{ forloop.parentloop.counter }}
5 {{ forloop.counter }}
6 {{ k}}
7 {% endfor %}
8 {% endfor %}
9 </p>

因为每个地方循环多次所以出现多次11 和22,后端传来的列表:rend_list={'中国':['北京','沈阳','大连'],'韩国':['首尔','普吉岛']}
这个循环只能在for循环中使用,遇到{%enfor%}标志就跳出循环,forloop对象就不能进行访问了。
在模板中比较2个参数的值。
使用标签{%ifequal%}和{%enequal%}支持标签{%else%}还有不相等{%ifnoequal%}
1 <p>
2 {% ifequal render 'evil' %}
3 welcome evil !
4 {% else %}
5 welcome anyone !
6 {% endifequal %}
7 </p>
后端传来的变量:
1 def tem(request):
2 user='evil'
3 return render(request,'1.html',{'render':user})
效果:

只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数。下面是合法参数的例子:
1 {% ifequal variable 1 %}
2 {% ifequal variable 1.23 %}
3 {% ifequal variable 'foo' %}
4 {% ifequal variable "foo" %}
其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在 {% ifequal %} 中。 下面是些错误的
1 {% ifequal variable True %}
2 {% ifequal variable [1, 2, 3] %}
3 {% ifequal variable {'key': 'value'} %}
django模板引用
include 模板包含:对于在html文档中,如果一部分内容多次出现的话,需要考虑写一个单独的模板。来进行引用。类似于函数的作用,减少重复代码的书写。
使用到标签{%include% 变量或者字符串的路径 }
views:
1 def home3(request):
2 return render(request,'mian.html',{'user':'evil'})
template:
layout.html
1 <h1>this is include part! login user {{ user }}</h1>
main.html
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 </head>
7 <body>
8 {% include 'layout.html' %}
9 <h2>this is body!</h2>'
10 </body>
11 </html>
效果:

注意:
- 当我们后端传给指定的html文档的时候,在指定文档中,如果包含其他模板的时候,其他模板可以引用指定模板的变量。如上例子!
模板的引用:
上面介绍的是减少部分的html的重复,但是如果遇到整个html文件的时候,比如一个website中,导航栏是必须的,其他内容不断变幻,怎么解决这个页面的代码的重复性?
在django中,可以使用{%include%}标签,但是在django中首选的是:模板的继承。
模板继承:
模板的继承最大意义是母版的内容是子版的一部分,而且是子版不需要改变的内容,而母版中可以定义{%block name%}和{%endblock%}标签,来给子版继承母版之后进行扩展,一般母版有三个{%block%}标签,
即:css、js、content三部分内容。供子版进行扩展。子版只需在继承母版之后,书写相应的block标签进行书写内容即可。
1 {%extend 'xx.html'%}
2 {%block css%}//子版的css部分
3 {%endblock%}
4 {%block content%}//子版的html内容
5 {%endblock%}
6 {%block js%}//子版进行自定义的js
7 {%endblock%}
同样:后台传递给该子版的变量,可以应用在母版的里。
block.super:
如果有以下场景:
1、有一个模板想继承一套已经存在的子版和母版的情况,还想使用子版的内容在当前的模板的那使用{{block,super}}来实现。继承上个模板的内容。
以下模板关系:

首先,child1继承了layout模板,而child2继承了child1的模板。内容分别如下:
layout:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 <style>
7 body{
8 background-color: cornflowerblue;
9 }
10 </style>
11 </head>
12 <body>
13 {% block content %}
14 {% endblock %}
15 </body>
16 </html>
child1:
1 {% extends 'layout.html' %}
2
3 {% block content %}
4 <h1>this is child1!</h1>
5 {% endblock %}
child2:
1 {% extends 'child1.html' %}
2 {% block content %}
3 {{ block.super }}
4 <h1>this is child2!</h1>
5 {% endblock %}
child2继承child1,child1继承layout。
如果child2没有变量:{{block.super}}(即显示母版child1对应的块内的内容。)显示效果:

如果加上变量{{block.super}}效果如下:

即显示出母版child1的内容。
总结:
- 首先无论模板被继承多少次,他的初始继承的母版(layout.html)的样式和效果都会被继承。
- 在对应的block块中使用变量{{block.super}}的时候,会继承母版对应的块里的内容,给咱们提供了更多的扩展接口和灵活使用模板~!


浙公网安备 33010602011771号