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/的时候,整个流程:

  1. 进来的请求转入/home/.

  1. Django通过在ROOT_URLCONF配置来决定根URLconf.

  1. Django在URLconf中的所有URL模式中,查找第一个匹配/hello/的条目。

  1. 如果找到匹配,将调用相应的视图函数

  1. 视图函数返回一个HttpResponse

  1. 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}}的时候,会继承母版对应的块里的内容,给咱们提供了更多的扩展接口和灵活使用模板~!

 

学习是一种态度,坚持是质变的利器!
posted @ 2018-03-11 22:59  dion至君  阅读(389)  评论(0)    收藏  举报