2015年7月13日 星期一

Python筆記:Django整理

一連練習了一些Django的應用,在這邊在整理以及複習一下前幾篇使用過的一些東西,加深印象.

開啟專案

$ django-admin startproject projectName

開啟專案後執行runserver

$ python manage.py migrate #同步資料庫

$ python manage.py runserver
Validating models...

0 errors found
Django version 1.8.2, using settings 'xxx.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Admin模組

  1. 確認settings.py,INSTALLED_APPS的django.contrib.admin前面的#註解拿掉
  2. 確認urls.py,from django.contrib import admin以及admin.autodiscover()兩行的註解拿掉,然後在urlpatterns的最後一行url(r'^admin/', include(admin.site.urls))的註解也拿掉.
  3. 執行python manage.py createsuperuser,設定帳號密碼.
  4. 執行runserver,就可以在http://192..../admin看到以下畫面.

enter image description here

建立App

$ python manage.py startapp APP

專案裡建立一個叫做APP的資料夾.

Model

負責處理跟資料庫相關的事情.使用 Django Model 的來操作資料庫的優點之一,就是資料庫轉換相當方便,假設要從SQLite換到MySQL,雖然在資料庫中有些欄位的定義不一樣,但在Django Model中,程式碼幾乎不用修改就可以無痛的把資料庫整個換掉了。

Ex.

# APP/models.py
from django.db import models

# Create your models here.
class Profile(models.Model):
  name     = models.CharField(max_length = 50)
  age      = models.IntegerField()
  tel      = models.CharField(max_length = 30)
  address  = models.CharField(max_length = 100)
  email    = models.EmailField()

def __str__(self):
  return self.name
  • CharField – 字串欄位,適合像 title、location 這種有長度限制的字串。
  • TextField – 合放大量文字的欄位
  • URLField – URL 設計的欄位
  • DateTimeField – 日期與時間的欄位,使用時會轉成 Pythondatetime型別
    enter image description here
    專案的settings.py中,加入App. 這樣Django專案就知道我們有這個App了.
INSTALLED_APPS = (
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.sites',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  # Uncomment the next line to enable the admin:
  'django.contrib.admin',
  # Uncomment the next line to enable admin documentation:
  # 'django.contrib.admindocs',
  'author',
)

同步資料庫

$ python manage.py migrate
#migrate 指令會根據INSTALLED_APPS的設定,按照 app 順序建立或更新資料表,將你在 models.py 裡的更新跟資料庫同步。

執行syncdb之後,Django幫你建立了一個叫做author_profile的表格。

$ python manage.py syncdb

Django shell

可以讓你直接透過指令來操作物件,不用寫SQL語法,一樣可以做到資料的Create (新增)、Read (讀取)、Update (修改)、Delete (刪除) 功能。

$ python manage.py shell
#Create
>>> from trips.models import Post
>>> Post.objects.create(title='My First Trip', content='肚子好餓,吃什麼好呢?',  location='台北火車站')
<Post: Post object>

#Read
# XXX/models.py
from django.db import models

class Post(models.Model):
    ...
    created_at = models.DateTimeField(auto_now_add=True)
    def __str__(self):        #記得加這行
        return self.title

>>> Post.objects.all()
[<Post: My First Trip>]

#Update
#想修改資料時,可以使用 update 更新一筆或多筆資料:
>>> posts.update(location='捷運大安站')
2 #回傳的數字 2 指的是已被更新的資料筆數。

>>> posts[0].location
'捷運大安站'
>>> posts[1].location
'捷運大安站'

#Delete
>>> posts.delete()

View

enter image description here
處理 request 的流程如下:

  1. 瀏覽器送出 HTTP Request
    • Django 依據 URL Conf 分配至對應的 View
    • View 進行資料庫的操作或其他運算,並回傳 Http Response 物件
    • 瀏覽器依據 HTTP Response,顯示網頁畫面

view 其實是一個 function,處理 HttpRequest 物件,並回傳 HttpResponse 物件,大致說明如下:

  • 會收到HttpRequest 物件參數: Django 從網頁接收到 request 後,會將 request 中的資訊封裝產生一個 HttpRequest 物件,並當成第一個參數,傳入對應的 view function。
  • 需要回傳HttpResponse物件: HttpResponse 物件裡面包含:
    • HttpResponse.content
    • HttpResponse.status_code …等

設定View主要有兩個步驟:
1. 設定urls.py
2. 撰寫視圖函式

設定urls.py

url(r'^here/$', here)就是告訴Django,看到網域後面出現/here/就去call views.py裡面的function here來動作.

# /mysite/urls.py
from views import here                            # 從views.py中匯入here這個function

urlpatterns = [
         url(r'^here/$', here), # 加入此行
         url(r'^admin/', include(admin.site.urls)),
     ]

撰寫視圖函式

#/mysite/views.py

from django.http import HttpResponse

def here(request):
    return HttpResponse('Hello World!')

以上程式在做的事就是:

  1. 從 django.http 模組中引用 HttpResponse 類別
  2. 宣告 here 這個 View
  3. 當 here 被呼叫時,回傳包含字串 Hello World! 的 HttpResponse 物件。

網址設定

URL Conf

  • 通常定義在urls.py
  • 是一連串的規則 (url pattern)
  • Django 收到 request 時,會一一比對 URL Conf 中的規則,決定要執行哪個 view function

在Django的網址設定是交給一個叫做urls.py的檔案在管理(其實不限定只有一個,也可以多個/模組化的設定).

from django.conf.urls import include, url
from django.contrib import admin
from stores.views import home, store_list, store_detail

     urlpatterns = [
         url(r'^$', home, name='home'),
         url(r'^admin/', include(admin.site.urls)),
         url(r'^store/$', store_list, name='store_list'),
         url(r'^store/(?P<pk>\d+)/$', store_detail, name='store_detail'),
     ]

urls.py的主要功能,就是設定”當遇到某個網址的request的時候,請找指定的App裡的View的action處理”。

Ex.

url(r'^here/$', here),  

r'^here/$':是Python中正規表達式的寫法,^號代表配對開始,$號代表配對結束,所以該表達式代表的是網域後的字串要“完全”等於/here/才算配對成功

here前面並沒有寫出/,這是因為Django預設會幫你加上這個slash。

以上程式透過 url() function 傳入兩個參數 regex,view
url(regex,view)

  • regex – 定義的 URL 規則
    • 規則以 regular expression 來表達
    • r’^here/$’ 代表的是 here/ 這種 URL
  • view – 對應的 view function
    • 指的是 here 這個 view
    • 'trips.views.hello_world' – trips 裡的 views.py 中的 hello_world() function
url(r'^$', 'bookstore.book.views.index'),

表示「當遇到網址後面沒接東西的時候(也就是大家俗稱的”首頁”),請找book/views.py裡面的index方法處理」,前面的bookstore是整個專案的名稱。

url(r'^books/(?P<book_id>\d+)/$', 'bookstore.book.views.detail'),

意思是假設遇到http://127.0.0.1:8000/books/100的網址候,100會被當做book_id傳給book/views.py的detail方法當做參數。

def home(request):
       return render(request, 'home.html')

在views.py裡的方法,通常我們會稱它叫做action,每個action方法的第一個參數,一定都是http request,每個action的回傳值,一定要是一個HttpResponse。views.py在一般的MVC架構裡,大概就是Controller之類的角色。

Template

Django雖然是Python寫的,但不同的是不可以在Template裡寫Python的程式碼,你在Template只能用Template提供的API,以及一些filter跟tag(不管是內建或是自己寫的)。
shortcuts: 用loader把template抓出來,再把結果render出來,變成一行render就搞定

#第一件事情先建立資料夾.

$ mkdir templates
from django.shortcuts import render

def home(request):
       return render(request, 'home.html')

這次傳入的參數有:

  • request – HttpRequest 物件
  • template_name – 要使用的 Template
  • dictionary – 包含要新增至 Template 的變數

Render :產生 HttpResponse 物件。

render(request, template_name, dictionary)
Ex.

from django.shortcuts import render

def hello_world(request):
    return render(request,
                  'hello_world.html',
                  {'current_time': datetime.now()})

Template API

Ex.

{% for store in stores %}
     <div class="store">
     <h2><a href="{% url 'store_detail' pk=store.pk %}">{{ store.name }}</a></h2>
     <p>{{ store.notes }}</p>
     </div>
     {% endfor %}

這些程式碼,是可以寫在.html裡的,反正到時候Django會把.html當做Template讀出來之後再解析它,最後把內容render給使用者看。

在Template裡,如果看到{% .. %}的,表示它是一個邏輯運算或是語法,通常不會有輸出值;而看到{{ .. }}的話,就是會把裡面的值吐出來放HTML裡的。

#forloop
{% for <element> in <list> %}
    ...
{% endfor %}

#if...else
{% if condition %}
    ...
{% else %}
    ...
{% endif %}

Filters

在Django中”資料呈現”的工作,只要交給Template的Filter來做就可以了.Template的Filter有點像在Linux系統上的pipe,就是可以透過|符號,把前面的資料丟給下一個執行,直到最後結束為止,filter在用的時候,|的左右不可以有空白,不然會直接出現TemplateSyntaxError

{{<variable_name>|<filter_name>:<filter_arguments>}}
  • < variable_name > – 變數名稱
  • < filter_name > – filter 名稱,例如add, cut等等
  • < filter_arguments > – 要傳入 filter 的參數
    Ex.
#將 created_at 時間,以 年 / 月 / 日 的形式顯示:
{{ post.created_at|date:"Y / m / d" }}

想要在最一開始列出食物的總項目數量的話,可以借助過濾器length使用|來接收前面的資料並做處理.

Model->Template

資料也可以從admin後台Shell來做新增/修改/刪除/更新。
資料庫透過Store類別給取出來,然後再以dictionary型式傳給render. 就可以將值傳給上述的Ex中,讓Template裡就可以取用得到Store這個變數。

def store_list(request):
      stores = Store.objects.all()
      return render(request, 'store_list.html',{'stores': stores})
def store_detail(request, pk):
      try:
          store = Store.objects.get(pk=pk)
      except Store.DoesNotExist:
          raise Http404
      return render(request, 'store_detail.html',{'store': store})

Http404,意思就是說如果資料庫裡面找不到這筆資料的話,就會直接丟出HTTP 404的畫面。

Regex

Django 的 URL 是一個 Regular Expression (Regex)。Regular expression 可用來描述一個字串的樣式。

(?P<id>\d+)
  • \d 代表一個阿拉伯數字。
  • + 代表「一個以上」。
    所以 \d+ 代表一個以上的阿拉伯數字,例如「0」、「99」、「12345」。可是像「8a」就不符合,因為「a」不是數字。
  • (?P<id>) 代表「把這一串東西抓出來,命名為 id。

所以 (?P<id>\d+) 代表:抓出一個以上阿拉伯數字,並把抓出來的東西取名為 id。

參考:
https://docs.djangoproject.com/en/1.8/
http://blog.eddie.com.tw/
http://djangogirlstaipei.gitbooks.io/django-girls-taipei-tutorial/content/django/templates.html

沒有留言:

張貼留言