前言: 各位久等了,django进阶篇来了。html
接口规范: url不能写动词,只能写名词前端
django默认只支持两种方式: get, postpython
get是获取数据mysql
?user=zcl&password=abc&email=669@qq
?号表示后面是参数,&在两参数中间程序员
request.GET.get("password")
上面这句代码可获取密码abc,是明文的!!web
post获取密码是密文的。post请求用于建立或修改数据。sql
if request.method == 'GET':
# <view logic>
return HttpResponse('result')
你可能已经注意到咱们在例子视图中返回文本的方式有点特别。 也就是说,HTML被直接硬编码在 Python 代码之中。shell
1 def current_datetime(request): 2 now = datetime.datetime.now() 3 html = "<html><body>It is now %s.</body></html>" % now 4 return HttpResponse(html)
尽管这种技术便于解释视图是如何工做的,但直接将HTML硬编码到你的视图里却并非一个好主意。 让咱们来看一下为何:数据库
基于这些缘由,将页面的设计和Python的代码分离开会更干净简洁更容易维护。 咱们可使用 Django的 模板系统 (Template System)来实现这种模式。django
1 >>> from django.template import Context, Template 2 >>> t = Template('My name is {{ name }}.') 3 >>> c = Context({'name': 'Stephane'}) 4 >>> t.render(c) 5 u'My name is Stephane.'
同一模板,多个上下文: 一旦有了 模板 对象,你就能够经过它渲染多个context
1 >>> from django.template import Template, Context 2 >>> t = Template('Hello, {{ name }}') 3 >>> print t.render(Context({'name': 'John'})) 4 Hello, John 5 >>> print t.render(Context({'name': 'Julie'})) 6 Hello, Julie 7 >>> print t.render(Context({'name': 'Pat'})) 8 Hello, Pat
不管什么时候咱们均可以像这样使用同一模板源渲染多个context,只进行 一次模板建立而后屡次调用render()方法渲染(render)会更为高效:
1 # Bad
2 for name in ('John', 'Julie', 'Pat'): 3 t = Template('Hello, {{ name }}') 4 print t.render(Context({'name': name})) 5 6 # Good 生成模版实例是有系统开销的,一个模版实例是能够进行屡次上下文的渲染
7 t = Template('Hello, {{ name }}') 8 for name in ('John', 'Julie', 'Pat'): 9 print t.render(Context({'name': name}))
注意: 若是没有python manage.py shell 是会曝错的!!这句代码的意义是导入django环境。
在到目前为止的例子中,咱们经过 context 传递的简单参数值主要是字符串,然而,模板系统可以很是简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。
在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。
向模板传递一个 Python 字典。 要经过字典键访问该字典的值,可以使用一个句点:
1 >>> from django.template import Template, Context 2 >>> person = {'name': 'Sally', 'age': '43'} 3 >>> t = Template('{{ person.name }} is {{ person.age }} years old.') 4 >>> c = Context({'person': person}) 5 >>> t.render(c) 6 u'Sally is 43 years old.'
一样,也能够经过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有 year 、 month 和 day 几个属性,你一样能够在模板中使用句点来访问这些属性:
1 >>> from django.template import Template, Context 2 >>> import datetime 3 >>> d = datetime.date(1993, 5, 2) 4 >>> d.year 5 1993
6 >>> d.month 7 5
8 >>> d.day 9 2
10 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') 11 >>> c = Context({'date': d}) 12 >>> t.render(c) 13 u'The month is 5 and the year is 1993.'
句点也可用于访问列表索引,例如:
1 >>> from django.template import Template, Context 2 >>> t = Template('Item 2 is {{ items.2 }}.') 3 >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) 4 >>> t.render(c) 5 u'Item 2 is carrots.'
效果图(太牛啦):
输入url经过路由调用index方法:
1 def index(request): 2 if request.method == "GET": 3 user_info = [{"username":"zcl_1","name":"zhang CL",}, 4 {"username": "zcl_2", "name": "zhang CL", }, 5 {"username": "zcl_3", "name": "zhang CL", }, 6 {"username": "zcl_4", "name": "zhang CL", }, 7 {"username": "zcl_5", "name": "zhang CL", },] 8
9 return render(request, "app01/index.html", {"user_objs":user_info})
app01/index.html下部分代码:
1 <ul>
2 {% for user_obj in user_objs %} 3 {# {% if forloop.counter0 > 2 %}#} 4 {% if forloop.counter0|divisibleby:"2" %} 5 <li style="background-color: darksalmon">username:{{ user_obj.username }};name:{{ user_obj.name }}</li>
6 {% else %} 7 <li style="">username:{{ user_obj.username }};name:{{ user_obj.name }}</li>
8 {% endif %} 9 {% endfor %} 10 </ul>
注意: forloop.counter0表示循环从0开始,divisibleby:"2"表示能被2整除的。PS: 千万不要写成divisibleby: "2"(中间加个空格,会曝错的!!当时我就加了空格,出错时一脸懵比...)
Templates/app01/page1.html文件:
1 <body>
2 {% extends "app01/index.html" %} {#继承父模版#} 3 <h1>page1</h1>
4 </body>
5
6 Templates/app01/index.html文件: 7 <body>
8 <ul>
9 <li style="display: inline">Home</li>
10 <li style="display: inline">page1</li>
11 <li style="display: inline">page2</li>
12 <li style="display: inline">page3</li>
13 </ul>
14 <h1>welcome to payment index</h1>
15
16 <footer>
17 <h1>foot</h1>
18 </footer>
19 </body>
Templates/app01/index.html文件:
1 <body> 2 <ul> 3 <li style="display: inline">Home</li> 4 <li style="display: inline">page1</li> 5 <li style="display: inline">page2</li> 6 <li style="display: inline">page3</li> 7 </ul> 8 <h1>welcome to payment index</h1> 9 10 <footer> 11 <h1>foot</h1> 12 </footer> 13 </body>
渲染page1.html文件效果图:
问题: 发现虽然能够继承父模版index.html,可是子模版page1.html的内容被覆盖。默认所有继承父模版!!
如何解决这个问题呢? 实际需求上,好比一个网站的上方菜单栏,前端界面基本是同样的,不一样页面会有微小的不一样。这时我想,我能够作一个网站的菜单栏做为父模版,该父模版能够被其它页面继承(extends)或复用(include).
如今我有个需求,我只想替换父模版index.html的 welcome to payment index:
Templates/app01/index.html文件:用block将须要被替换的内容包含起来。
{% block content-container %} <h1>welcome to payment index</h1> {% endblock %}
Templates/app01/page1.html文件: 用block将要替换父模版的内容包含起来。
<body> {% extends "app01/index.html" %} {% block content-container %} {# 重写父模版的content-container部分 #} <h1>page1</h1> {% endblock %} </body>
继承效果图:
复用就简单了,重复地使用嘛,好比我在register.html写一个注册的表单,只要网站的页面有须要注册,直接复用以前写的表单就OK了
{% include "app01/register.html" %}
Templates/app01/page1.html文件:
1 <body> 2 {% extends "app01/index.html" %} 3 {% block content-container %} 4 <h1>page1</h1> 5 {% include "app01/register.html" %} 6 {% endblock %} 7 </body>
Templates/app01/register.html:
<body> <div style="background-color: antiquewhite"> <form> Username:<input name="username" type="text"> Password:<input name="password" type="password"> </form> </div> </body>
继承+复用效果图(图中form表单是复用来的~):
django 自己提供了很是强大易使用的ORM组件,而且支持多种数据库,如sqllite,mysql,progressSql,Oracle等,固然最经常使用的搭配仍是mysql,要启用orm,先要配置好链接数据 的信息。
为了更好的理解,咱们来作一个基本的 书籍/做者/出版商 数据库结构。 咱们这样作是由于 这是一个众所周知的例子,不少SQL有关的书籍也经常使用这个举例。
咱们来假定下面的这些概念、字段和关系:
一个做者有姓,有名及email地址。
出版商有名称,地址,所在城市、省,国家,网站。
书籍有书名和出版日期。 它有一个或多个做者(书和做者是多对多的关联关系[many-to-many]), 只有一个出版商(书和出版商是一对多的关联关系[one-to-many],也被称做外键[foreign key])
第一步:在配置文件加入app名(我建立的app名为app01)
第二步: 我mysqldb装不上,为了方便用默认的sqllite数据库~
用默认的sqlite数据库,就啥都不用改,直接看第三步;固然若是你mysqldb模块装上了,能够用mysql数据库试试,可在settings.py改下数据库链接的配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'OldboyWebsite', #确保此数据库已存在 'HOST':'', 'PORT':'', 'USER':'root', 'PASSWORD':'' } }
第三步: 建立表结构
1 from django.db import models 2
3 # Create your models here.
4 class Author(models.Model): 5 first_name = models.CharField(max_length=32) 6 last_name = models.CharField(max_length=32) 7 email = models.EmailField() 8
9 def __str__(self): 10 return "<%s %s>" % (self.first_name,self.last_name) 11
12 class Meta: 13 verbose_name_plural = u"做者"
14
15 class Publisher(models.Model): 16 name = models.CharField(max_length=64, unique=True) 17 address = models.CharField(max_length=128,null=True,blank=True) 18 city = models.CharField(max_length=64) 19 state_province = models.CharField(max_length=64,help_text="put your province here",verbose_name=u"所属省") 20 country = models.CharField(max_length=64,editable=False) 21 website = models.URLField() 22
23 def __str__(self): 24 return "<%s>" % (self.name) 25
26 class Book(models.Model): 27 name = models.CharField(max_length=128) 28 authors = models.ManyToManyField(Author) #书多对多到做者
29 publisher = models.ForeignKey(Publisher) #一对多
30 publish_date = models.DateField() #精确到天DateField()
31
32 def __str__(self): 33 return "<%s %s>" % (self.name,self.publisher)
看上面的代码,若是你看过我以前的博客sqlalchemy orm和堡垒机表结构设计,就会发现django orm进行多对多关联时不用本身来生成中间表,天呐!!这可方便了!!
你可能看不懂上面的help_text,verbose_name,editable,class Meta:,def __str__(self):.....这些我等下讲,慢慢来,一会儿就高潮就很差了哈哈。
第四步: 为了能在django后台的管理员能查看到生成的表,在app01/admin.py文件添加下面代码:
第五步: 同步数据库
第六步: 建立superuser
第七步: 登录admin并建立数据
注意: 在建立表结构时,若是不在表对象中加入def __str__(self):方法(python3下),则会出现下面状况:没法显示出书的名称。 Python2对应为def __unicode__(self):
模型字段我这里讲几个意思意思就行了,更多的请参考官方文档。
更多models field 字段:https://docs.djangoproject.com/en/1.9/ref/models/fields/
1. null & blank
address = models.CharField(max_length=128,null=True)
在出版社表的address字段加上null = True; 此时address在admin后台仍不能为空!
必须再加上bland = True; 限制django admin可为空。
六级没过的我,差15分……来看段官方英文热热身……只要你看得懂,会发现英文真TM易懂,由于英文不会有歧义。
2. editable = False 表示不能更改
我大天朝的国籍企是你想改就能改的……
country = models.CharField(max_length=64,editable=False)
3. help_text = "xx" 提示文字 不是对数据库的修改,是对django admin页面的修改,因此当你增长这个字段,你是不用去同步数据库的。
state_province = models.CharField(max_length=64,help_text="put your province here")
4. verbose_name 详细的名字
state_province = models.CharField(max_length=64,help_text="put your province here",verbose_name=u"所属省")
5. class Meta: 若是想本身在django后台定义表名,可在表结构加上下面的代码:
class Meta: verbose_name_plural = u"做者"
上图!!
查找类型有:icontains(大小写不敏感的LIKE),startswith和endswith, 还有range
关于修改,有个点要注意下:
在“插入和更新数据”小节中,咱们有提到模型的save()方法,这个方法会更新一行里的全部列。 而某些状况下,咱们只须要更新行里的某几列。
例如说咱们如今想要将Apress Publisher的名称由原来的”Apress”更改成”Apress Publishing”。若使用save()方法,如:
>>> p = Publisher.objects.get(name='Apress') >>> p.name = 'Apress Publishing' >>> p.save()
这等同于以下SQL语句:
SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name = 'Apress'; UPDATE books_publisher SET name = 'Apress Publishing', address = '2855 Telegraph Ave.', city = 'Berkeley', state_province = 'CA', country = 'U.S.A.', website = 'http://www.apress.com' WHERE id = 52;
(注意在这里咱们假设Apress的ID为52)
在这个例子里咱们能够看到Django的save()方法更新了不只仅是name列的值,还有更新了全部的列。 若name之外的列有可能会被其余的进程所改动的状况下,只更改name列显然是更加明智的。 更改某一指定的列,咱们能够调用结果集(QuerySet)对象的update()方法: 示例以下:
>>> Publisher.objects.filter(id=52).update(name='Apress Publishing')
与之等同的SQL语句变得更高效,而且不会引发竞态条件。
UPDATE books_publisher SET name = 'Apress Publishing' WHERE id = 52;
update()方法对于任何结果集(QuerySet)均有效,这意味着你能够同时更新多条记录。 如下示例演示如何将全部Publisher的country字段值由’U.S.A’更改成’USA’:
>>> Publisher.objects.all().update(country='USA') 2
咱们已经知道如何对数据进行过滤和排序。 固然,一般咱们须要同时进行过滤和排序查询的操做。 所以,你能够简单地写成这种“链式”的形式:
>>> Publisher.objects.filter(country="U.S.A.").order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>]
你应该没猜错,转换成SQL查询就是 WHERE 和 ORDER BY 的组合:
SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE country = 'U.S.A' ORDER BY name DESC;
如今你找到了一本书的对象b1, 书与做者已经进行多对多关联,此时你想知道书的做者是谁?
删除b1这本书,看下图,删除b1时会把书与做者中间表对应内容也删除,真牛!!
参考博客: http://www.cnblogs.com/alex3714/articles/5457672.html 大王这篇博客写得太乱了……
写很久,脖子酸