django進階-1

前言: 各位久等了,django進階篇來了。html

1、get與post

接口規範: 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')

  

2、模版渲染

你可能已經注意到咱們在例子視圖中返回文本的方式有點特別。 也就是說,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 代碼進行相應的修改。 站點設計的修改每每比底層 Python 代碼的修改要頻繁得多,所以若是能夠在不進行 Python 代碼修改的狀況下變動設計,那將會方便得多。
  • Python 代碼編寫和 HTML 設計是兩項不一樣的工做,大多數專業的網站開發環境都將他們分配給不一樣的人員(甚至不一樣部門)來完成。 設計者和HTML/CSS的編碼人員不該該被要求去編輯Python的代碼來完成他們的工做。
  • 程序員編寫 Python代碼和設計人員製做模板兩項工做同時進行的效率是最高的,遠勝於讓一我的等待另外一我的完成對某個既包含 Python又包含 HTML 的文件的編輯工做。

基於這些緣由,將頁面的設計和Python的代碼分離開會更乾淨簡潔更容易維護。 咱們可使用 Django的 模板系統 (Template System)來實現這種模式。django

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環境

 

3、深度變量的查找

在到目前爲止的例子中,咱們經過 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.'

 

4、隔行更換背景顏色

效果圖(太牛啦):

輸入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"(中間加個空格,會曝錯的!!當時我就加了空格,出錯時一臉懵比...)

 

5、模版的繼承與複用

 

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>
View Code

渲染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表單是複用來的~):

 

6、django orm

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):

 

model field

模型字段我這裏講幾個意思意思就行了,更多的請參考官方文檔。

更多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"做者"

 

7、增刪改查

上圖!!

查找類型有: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  大王這篇博客寫得太亂了……

寫很久,脖子酸

轉發註明出處: http://www.cnblogs.com/0zcl/p/6562380.html 

相關文章
相關標籤/搜索