1.1 安裝python包管理器:php
wget https://bootstrap.pypa.io/get-pip.py sudo python get-pip.py
1.2 安裝python虛擬環境virtualenv virtualenvwrappercss
首先說明下爲何要裝這兩個包:html
First, it’s important to understand that a virtual environment is a special tool used to keep the dependencies required by different projects in separate places by creating isolated, independent Python environments for each of them.java
In short, it solves the 「Project X depends on version 1.x, but Project Y needs 4.x」 dilemma. It also keeps your global site-packages neat, tidy, and free from clutter.node
If you would like a full explanation on why Python virtual environments are good practice, absolutely give this excellent blog post on RealPython a read.python
用虛擬開發環境能夠爲每一個工程提供獨立的python開發環境、獨立的包、獨立的版本,每一個獨立的環境會在~/.virtualenvs/下造成資源包~mysql
sudo pip install virtualenv virtualenvwrapper sudo rm -rf ~/.cache/pip
以後在~/.profile文件最後添加下面幾行:linux
# virtualenv and virtualenvwrapper export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
以後若是想用python虛擬環境,在每次打開一個新的terminal就要執行一次source ~/.profilenginx
source ~/.profile
接下來咱們生成一個python虛擬環境來用於python-web的開發提供環境:(這裏用的是python2.7)git
mkvirtualenv python_web -p python2
注:再次說明python虛擬環境是徹底獨立的,也就是說在python_web的環境下安裝的python包,步適用於全局;在全局安裝的包,不適合python_web。
如何驗證你如何將python_web環境生成好了呢?——新開一個terminal,執行下列命令:
source ~/.profile workon python_web
若是terminal前面的文字變成了(python_web)代表成功建立了名爲cv的python虛擬環境;
從官網上得知2.7版本的python可以使用最高1.11版本的Django,所以在python_web環境中安裝:
pip install Django==1.11
測試Django有沒有安裝成功,進入python命令交互模式:
import django django.VERSION
找到你的django-admin.py文件,並把它加入系統路徑。若是用的是setup.py工具安裝的Django,django-admin.py應該已被加入了系統路徑中。個人django-admin.py的目錄爲:
/root/.virtualenvs/python_web/lib/python2.7/site-packages/django/bin
進入該目錄下,運行以下命令,新建一個項目:
python django-admin.py startproject mysite
startproject命令建立一個目錄,包含一個名爲mysite的文件夾和一個名爲manage.py的文件。其中mysite文件夾下包含有四個文件,分別爲:
(python_web) ➜ mysite tree . ├── db.sqlite3 ├── manage.py └── mysite ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py
爲了安裝後更多的體驗,讓咱們運行一下django開發服務器看看咱們的準系統。django開發服務是可用在開發期間的,一個內建的,輕量的web服務。 咱們提供這個服務器是爲了讓你快速開發站點,也就是說在準備發佈產品以前,無需進行產品級 Web 服務器(好比 Apache)的配置工做。 開發服務器監測你的代碼並自動加載它,這樣你會很容易修改代碼而不用重啓動服務。若是你還沒啓動服務器的話,請切換到你的項目目錄裏 (cd mysite),運行下面的命令:
python manage.py runserver
你會看到以下內容:
Django version 1.11, using settings 'mysite.settings' Starting development server at http://127.0.0.1:3000/ Quit the server with CTRL-BREAK
這將會在端口3000啓動一個本地服務器, 而且只能從你的這臺電腦鏈接和訪問。 既然服務器已經運行起來了,如今用網頁瀏覽器訪問 http://127.0.0.1:8000/ 。 你應該能夠看到一個使人賞心悅目的淡藍色Django歡迎頁面。 代表它開始工做了。
可是個人服務器搭在阿里雲上,而且綁定了phage.cc的域名,所以能夠經過這樣的方式使之能訪問:
python manage.py runserver 0.0.0.0:3000
注:0.0.0.0」這個IP地址,告訴服務器去偵放任意的網絡接口。
注:採用phage.cc:3000去訪問會報錯誤 alid HTTP_HOST header: 'www.phage.cc:3000'. You may need to add u'www.phage.cc' to ALLOWED_HOSTS.
能夠經過添加容許來實現經過:
settings.py : ALLOWED_HOSTS = [u'www.phage.cc']
4.1 靜態視圖hello world
在文件夾mysite中新建一個views.py的文件:
from django.http import HttpResponse def hello(request): return HttpResponse("Hello world")
在這段代碼中:咱們定義一個叫作hello 的視圖函數,這個函數只有簡單的一行代碼: 它僅僅返回一個HttpResponse對象,這個對象包含了文本「Hello world」。
注:每一個視圖函數至少要有一個參數,一般被叫做request。 這是一個觸發這個視圖、包含當前Web請求信息的對象,是類django.http.HttpRequest的一個實例。在這個示例中,咱們雖然不用request作任何事情,然而它仍必須是這個視圖的第一個參數。
注:視圖函數的名稱並不重要;並不必定非得以某種特定的方式命名才能讓 Django 識別它。 在這裏咱們把它命名爲:hello,是由於這個名稱清晰的顯示了視圖的用意。
4.2 URLconf將視圖和URL綁定(相似nodejs中的路由)
URLconf 就像是 Django 所支撐網站的目錄。 它的本質是 URL 模式以及要爲該 URL 模式調用的視圖函數之間的映射表。 你就是以這種方式告訴 Django,對於這個 URL 調用這段代碼,對於那個 URL 調用那段代碼。
這個映射表在urls.py中,咱們想要實現訪問/hello/調用hello視圖,返回hello world須要作下面樣子修改:
from django.conf.urls import url urlpatterns = [ url(r'^hello/$', hello), ]
注: 這裏的^hello/$是正則表達式,匹配全部/hello/形式的請求。
以後咱們運行該服務器,在瀏覽器中能夠訪問hello視圖: http://www.phage.cc:3000/hello/
4.3 動態內容視圖請求當前時間
在views.py中添加一個新視圖current_datatime:
from django.http import HttpResponse import datetime def hello(request): return HttpResponse("Hello world") def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
相似hello視圖,這裏用了python的datetime工具,獲取時間併合成一個html字符串,做爲視圖返回。
同理,咱們也須要在urls.py中作url映射:
from django.conf.urls import url from mysite.views import hello, current_datetime urlpatterns = [ url(r'^hello/$', hello), url(r'^time/$', current_datetime), ]
這樣咱們經過訪問 http://www.phage.cc:3000/time/ 能夠獲取time視圖返回。
4.4 動態URL視圖
在咱們的current_datetime
視圖範例中,儘管內容是動態的,可是URL ( /time/ )是靜態的。 在 大多數動態web應用程序,URL一般都包含有相關的參數。 舉個例子,一家在線書店會爲每一本書提供一個URL,如:/books/243/、/books/81196/。
讓咱們建立第三個視圖來顯示當前時間和加上時間誤差量的時間,設計是這樣的: /time/plus/1/ 顯示當前時間+1個小時的頁面 /time/plus/2/ 顯示當前時間+2個小時的頁面 /time/plus/3/ 顯示當前時間+3個小時的頁面,以此類推。
注: 在java或php中有可能見到這樣的實現:/time/plus?hours=3,但這樣被認爲不漂亮
以前咱們已經看到url是以正則表達式的形式出現,所以想要實現/time/plus/xxx/也就比較容易了:
from django.conf.urls import url from mysite.views import hello, current_datetime, hours_ahead urlpatterns = [ url(r'^hello/$', hello), url(r'^time/$', current_datetime), url(r'^time/plus/(\d{1,2})/$', hours_ahead), ]
那麼咱們如是實現hours_ahead來接收請求中的xxx數字呢?
from django.http import Http404, HttpResponse import datetime ... def hours_ahead(request, offset): try: offset = int(offset) except ValueError: raise Http404() dt = datetime.datetime.now() + datetime.timedelta(hours=offset) html = "<html><body>In %s hour(s), it will be %s.</body></html>" % (offset, dt) return HttpResponse(html)
hours_ahead 和咱們之前寫的 current_datetime 很象,關鍵的區別在於: 它多了一個額外參數,時間差。
注: offset 是從匹配的URL裏提取出來的。 例如:若是請求URL是/time/plus/3/,那麼offset將會是3;若是請求URL是/time/plus/21/,那麼offset將會是21。請注意:捕獲值永遠都是字符串(string)類型,而不會是整數(integer)類型,即便這個字符串全由數字構成(如:「21」)。
注: 在這裏咱們命名變量爲 offset ,你也能夠任意命名它,只要符合Python 的語法。 變量名是可有可無的,重要的是它的位置,它是這個函數的第二個 參數 (在 request 的後面)。 你還可使用關鍵字來定義它,而不是用 位置。
5.1 最簡單的模板DEMO
模板的好處是將python和html分開,下面是一個最簡單的例子:
def template_test(request): now = datetime.datetime.now() t = Template("<html><body>It is now {{ current_date }}.</body></html>"); html = t.render(Context({'current_date': now})) return HttpResponse(html)
上面的例子在html中嵌入一個 current_date 變量,經過context給變量賦值,經過render來渲染。除了雙大括號表示的變量,還有循環、條件等各類玩法: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/ 。
5.2 將html和python完全分離
可是上面咱們並無真正將html和python分離,更進一步的作法是將html單獨放置:
1) 在mysite下新建一個文件夾:templates,並在其中新建一個template_test1.html:
<html><body>It is now {{ current_date }}.</body></html>
2) 而咱們的template_test就能改形成:
def template_test1(request): now = datetime.datetime.now() t = get_template('template_test1.html'); html = t.render({'current_date': now}) return HttpResponse(html)
3) 最後咱們得經過下面方法讓get_template的輸入參數不用寫完整路徑:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),], 'APP_DIRS': True, 'OPTIONS': {
注:咱們還能夠用render_to_response來簡化template_test操做:
def template_test2(request): now = datetime.datetime.now() return render_to_response('template_test1.html', {'current_date': now})
5.3 模板繼承
一個多頁面的網站,其每一個頁面可能會有相同的頭部、尾部的結構,主頁面的內容存在更新變更。若是咱們爲每一個頁面單首創建一個獨立的html將會產生大量冗餘,此外若是咱們想要對全部頁面的頭部作一個修改,也將比較麻煩。此時咱們能夠採用模板的思想來完美解決這個問題:
1)新建一個母版html(base.html)
(python_web) ➜ templates git:(master) cat base.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site.</p> {% endblock %} </body> </html>
2) 建立一個繼承base.html的template_test2_use_base_1.html:
(python_web) ➜ templates git:(master) cat template_test2_use_base_1.html {% extends "base.html" %} {% block title %}The current time{% endblock %} {% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}
3) 再建立一個繼承base.html的template_test2_use_base_2.html:
(python_web) ➜ templates git:(master) cat template_test2_use_base_2.html {% extends "base.html" %} {% block title %}Future time{% endblock %} {% block content %} <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> {% endblock %}
可見base.html中的{% block title %}{% endblock %} 、{% block content %}{% endblock %} 、{% block footer %}{% endblock %} 均可以被繼承者們從新實現!
注:固然,若是繼承者沒有實現,則不會顯示。
6.1 安裝MYSQL數據庫
咱們先在linux上安裝數據庫:
sudo apt-get install mysql-server sudo apt-get install libmysqlclient-dev
安裝過程當中會提示設置密碼什麼的,注意設置了不要忘了,安裝完成以後可使用以下命令來檢查是否安裝成功:
sudo netstat -tap | grep mysql
經過上述命令檢查以後,若是看到有mysql 的socket處於 listen 狀態則表示安裝成功。
登錄mysql數據庫能夠經過以下命令:
mysql -u root -p
-u 表示選擇登錄的用戶名, -p 表示登錄的用戶密碼,上面命令輸入以後會提示輸入密碼,此時輸入密碼就能夠登陸到mysql。
下面是一些命令行中操做的DEMO,可作從此參考:
mysqladmin -u root -p create blog mysql mysql -u root -p show databases; use blog; CREATE TABLE IF NOT EXISTS `blog_table`( `blogId` BIGINT UNSIGNED, `url` VARCHAR(100) NOT NULL, `title` VARCHAR(1000) NOT NULL, `support` INT UNSIGNED, `pageView` INT UNSIGNED, PRIMARY KEY ( `blogId` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `tag_table`( `tagId` INT UNSIGNED AUTO_INCREMENT, `tagName` VARCHAR(100) NOT NULL, PRIMARY KEY ( `tagId` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `blog_tag_relation_table`( `relationId` INT UNSIGNED AUTO_INCREMENT, `blogId` BIGINT UNSIGNED, `tagId` INT UNSIGNED, PRIMARY KEY ( `relationId` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; show tables; desc blog_table; desc tag_table; desc blog_tag_relation_table; //change blogId int 2 bigint alter table blog_table change blogId blogId BIGINT UNSIGNED; //show data select * from blog_table; //delete data delete from blog_table where blogId=201801021423; INSERT INTO blog_table(blogId,url,title,support,pageView) VALUES(201801021423,'http://106.14.226.191:3000/blog/201607281658.html','[商業_法務] 一、公司一款新消費類電子產品如何快速全面的專利保護',0,0); //too short alter table blog_table change title title VARCHAR(1000) NOT NULL; INSERT INTO tag_table(tagId,tagName) VALUES(0,'硬件_模擬電路'); select * from blog_table; select * from tag_table; select * from blog_tag_relation_table; delete from blog_table where blogId>0; delete from tag_table where tagId>=0; delete from blog_tag_relation_table where relationId >= 0; select a.title , a.url, b.tagName from blog_table a, tag_table b, blog_tag_relation_table c WHERE a.blogId = c.blogId AND a.blogId = 201602021408 AND b.tagId = c.tagId; select a.title , a.url, b.tagName from blog_table a, tag_table b, blog_tag_relation_table c WHERE a.blogId = c.blogId AND b.tagId = c.tagId ORDER BY b.tagId;
爲了python操做mysql須要執行下面命令:
pip install MySQL-python
6.2 配置及測試數據庫
在settings.py中下面幾項是對數據庫的配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'pyserver', 'USER': 'root', 'PASSWORD': '123456', } }
一旦在輸入了那些設置並保存以後應當測試一下你的配置。 咱們能夠在mysite
項目目錄下執行python manage.py shell
來進行測試(沒有錯誤表示成功):
from django.db import connection cursor = connection.cursor()
6.3 建立books app
在mysite
項目文件下輸入下面的命令來建立books
app:
python manage.py startapp books
這個命令並無輸出什麼,它只在 mysite 的目錄裏建立了一個 books 目錄。 讓咱們來看看這個目錄的內容:
(python_web) ➜ books tree . ├── admin.py ├── apps.py ├── __init__.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py
這個目錄包含了這個app的模型和視圖。
6.4 編寫模型
編輯models.py
:
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField()
Publisher 模塊至關於SQL語句:
CREATE TABLE "books_publisher" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(30) NOT NULL, "address" varchar(50) NOT NULL, "city" varchar(60) NOT NULL, "state_province" varchar(30) NOT NULL, "country" varchar(50) NOT NULL, "website" varchar(200) NOT NULL );
6.5 由模型自動生成建立表SQL
再次編輯settings.py,將下面列出選項加#
註釋掉,並添加‘mysite.books’
到INSTALLED_APPS
的末尾:
INSTALLED_APPS = [ #'django.contrib.admin', #'django.contrib.auth', #'django.contrib.contenttypes', #'django.contrib.sessions', #'django.contrib.messages', #'django.contrib.staticfiles', 'books', ] MIDDLEWARE = [ #'django.middleware.security.SecurityMiddleware', #'django.contrib.sessions.middleware.SessionMiddleware', #'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', #'django.contrib.auth.middleware.AuthenticationMiddleware', #'django.contrib.messages.middleware.MessageMiddleware', #'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
你可能會執行python manage.py validate ,而後你會特別傷心的看到人家提示Unknown command: 'validate'Type 'manage.py help' for usage.,對吧?因此你要用以下這個命令:
python manage.py check
而後你還想生成sql語句,你就運行了python manage.py sqlall books,錯誤提示是Unknown command: 'sqlall'Type 'manage.py help' for usage.一樣若是你想提交sql語句到數據庫而運行syncdb,錯誤提示是Unknown command: 'syncdb'
Type 'manage.py help' for usage. 爲何沒有這些命令,由於它們被淘汰了。因此你只需運行以下的命令:
python manage.py makemigrations books #用來檢測數據庫變動和生成數據庫遷移文件 python manage.py migrate #用來遷移數據庫(直接到數據庫) python manage.py sqlmigrate books 0001 # 用來把數據庫遷移文件轉換成數據庫語言
6.6 基本數據訪問
一旦你建立了模型,Django自動爲這些模型提供了高級的Python API。 運行 python manage.py shell 並輸入下面的內容試試看:
>>> from books.models import Publisher >>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue', ... city='Berkeley', state_province='CA', country='U.S.A.', ... website='http://www.apress.com/') >>> p1.save() >>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.', ... city='Cambridge', state_province='MA', country='U.S.A.', ... website='http://www.oreilly.com/') >>> p2.save() >>> publisher_list = Publisher.objects.all() >>> publisher_list [<Publisher: Publisher object>, <Publisher: Publisher object>]
其餘經常使用基本操做以下:
p1 = Publisher.objects.create(....)
p1.name = 'Apress Publishing'
Publisher.objects.filter(country="U.S.A.", state_province="CA")
Publisher.objects.get(name="Apress")
Publisher.objects.order_by("state_province", "address")
Publisher.objects.filter(country="U.S.A.").order_by("-name")
Publisher.objects.order_by('name')[0]
or [0:2]
Publisher.objects.filter(id=52).update(name='Apress Publishing')
p.save()
p.delete()
注意:上述操做除了刪除,每一個操做以後都別忘了保存!
7.1 基本操做
編輯settings.py:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'books', ] MIDDLEWARE = [ #'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', #'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', #'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
以後運行python manage.py migrate
這一步將生成管理界面使用的額外數據庫表。 當你把'django.contrib.auth'加進INSTALLED_APPS後,第一次運行syncdb命令時, 系統會請你建立一個超級用戶。 若是你不這麼做,你須要運行python manage.py createsuperuser來另外建立一個admin的用戶賬號,不然你將不能登入admin(我這裏設置user:admin password:xxxxxx)
將admin訪問配置在URLconf(記住,在urls.py中)
from django.conf.urls import url from django.contrib import admin from django.conf.urls import include #from mysite.views import hello from mysite.views import hello, current_datetime, hours_ahead, template_test, template_test1, template_test2, template_test3, template_test4 admin.autodiscover() urlpatterns = [ url(r'^admin/', include(admin.site.urls)), ... ]
此時運行python manage.py runserver 0.0.0.0:8080
,而後在瀏覽器中訪問: http://www.phage.cc:8080/admin/
注:NameError: name 'include' is not defined錯誤須要from django.conf.urls import include;
注:django nginx admin css丟失須要在settings.py中INSTALLED_APPS中加django.contrib.staticfiles;
7.2 管理工具簡介
管理界面的設計是針對非技術人員的,因此它應該是自我解釋的。 儘管如此,這裏簡單介紹一下它的基本特性:
1)登陸頁面(用戶名密碼就是剛剛生成的admin,xxxxxxxxx)
你要使用你原來設置的超級用戶的用戶名和密碼。 若是沒法登陸,請運行python manage.py createsuperuser
,確保你已經建立了一個超級用戶。
2)一旦登陸了,你將看到管理頁面:
這個頁面列出了管理工具中可編輯的全部數據類型。 如今,因爲咱們尚未建立任何模塊,因此這個列表只有寥寥數條類目: 它僅有兩個默認的管理-編輯模塊:用戶組(Groups)和用戶(Users)。
3)點進去USER能夠添加、修改、刪除等操做,很是方便:
7.3 將其餘Models加入到Admin管理中
有一個關鍵步驟咱們還沒作。 讓咱們將本身的模塊加入管理工具中,這樣咱們就可以經過這個漂亮的界面添加、修改和刪除數據庫中的對象了。 咱們將繼續第五章中的book
例子。在其中,咱們定義了三個模塊: Publisher 、 Author 和 Book 。
編輯mysite/books/admin.py
,而後輸入:
# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.contrib import admin from books.models import Publisher, Author, Book admin.site.register(Publisher) admin.site.register(Author) admin.site.register(Book) # Register your models here.
重啓服務器,如今再去admin主頁,就會看到Publisher 、 Author 和 Book模塊,這樣就能編輯這些模塊了!
7.4 工做原理
當服務啓動時,Django從url.py
引導URLconf,而後執行admin.autodiscover()
語句。 這個函數遍歷INSTALLED_APPS配置,而且尋找相關的 admin.py文件。 若是在指定的app目錄下找到admin.py,它就執行其中的代碼。
在books
應用程序目錄下的admin.py
文件中,每次調用admin.site.register()
都將那個模塊註冊到管理工具中。 管理工具只爲那些明確註冊了的模塊顯示一個編輯/修改的界面。
7.5 設置字段可選
email = models.EmailField(**blank=True** )
email = models.EmailField(blank=True, **verbose_name='e-mail'** )
自定義列表:
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(blank=True, verbose_name='e-mail') **def __unicode__(self):** **return u'%s %s' % (self.first_name, self.last_name)**
注:更多展現自定義能夠參考[12]. The Django Book - 第六章 Django站點管理
8.1 URL相關信息
HttpRequest對象包含當前請求URL的一些信息:
屬性/方法 | 說明 | 舉例 |
---|---|---|
request.path | 除域名之外的請求路徑,以正斜槓開頭 | "/hello/" |
request.get_host() | 主機名(好比,一般所說的域名) | "127.0.0.1:8000" or "www.example.com" |
request.get_full_path() | 請求路徑,可能包含查詢字符串 | "/hello/?print=true" |
request.is_secure() | 若是經過HTTPS訪問,則此方法返回True, 不然返回False | True 或者 False |
8.2 一個簡單的SEARCH表單
views.search()
def search(request): error = False if 'q' in request.GET: q = request.GET['q'] if not q: error = True else: books = Book.objects.filter(title__icontains=q) return render_to_response('search_results.html',{'books': books, 'query': q}) return render_to_response('search_form.html',{'error': error})
search_form.html
<html> <head> <title>Search</title> </head> <body> {% if error %} <p style="color: red;">Please submit a search term.</p> {% endif %} <form action="" method="get"> <input type="text" name="q"> <input type="submit" value="Search"> </form> </body> </html>
search_results.html
<p>You searched for: <strong>{{ query }}</strong></p> {% if books %} <p>Found {{ books|length }} book{{ books|pluralize }}.</p> <ul> {% for book in books %} <li>{{ book.title }}</li> {% endfor %} </ul> {% else %} <p>No books matched your search criteria.</p> {% endif %}
更高級的用法咱們在後面的DEMO中介紹!
項目地址: https://github.com/zmrenwu/django-blog-tutorial
項目master: https://github.com/zmrenwu
9.1 將項目部署在咱們買AliYun上
下載項目到本地:
cd ~/App/ git clone https://github.com/zmrenwu/django-blog-tutorial.git
建立並激活虛擬環境(必定要注意是python3):
virtualenv blogproject_env -p python3 source blogproject_env/bin/activate
安裝依賴並數據遷移(sqlite的):
pip install -r requirements.txt python manage.py migrate
建立後臺管理員帳戶並啓動服務器(我這裏其餘端口被佔用,所以用8080):
python manage.py createsuperuser python manage.py runserver 0.0.0.0:8080
因爲咱們不是在本地運行,所以還得在settings.py中添加: ALLOWED_HOSTS = [u'www.phage.cc']
。此時,即可以訪問 http://www.phage.cc:8080/admin/ 對品類、文章、標籤、用戶等進行管理了:
訪問: http://www.phage.cc:8080/ 即可看到咱們在後臺添加的 python-django 文章:
9.2 代碼解析
首先看看全部支持的url入口配置文件:/blog/urls.py
from django.conf.urls import url from . import views app_name = 'blog' urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^post/(?P<pk>[0-9]+)/$', views.PostDetailView.as_view(), name='detail'), url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$', views.ArchivesView.as_view(), name='archives'), url(r'^category/(?P<pk>[0-9]+)/$', views.CategoryView.as_view(), name='category'), url(r'^tag/(?P<pk>[0-9]+)/$', views.TagView.as_view(), name='tag'), # url(r'^search/$', views.search, name='search'), ]
其主頁調用views.IndexView.as_view()實現的,可是爲何有第三個參數name='idnex'呢?咱們看/blog/view.py的IndexView就明白了,這裏類IndexView繼承Django的Generic display views來實現的,看一下Generic display views中的ListViewd的用法就明白了。其餘的各類入口則依此類推:
class IndexView(ListView): ... class PostDetailView(DetailView): ... class ArchivesView(ListView): ... class CategoryView(ListView): ... class TagView(ListView): ...
咱們倒着分析各個入口的實現(倒着由淺入深),看第一個TagView的實現:
class TagView(ListView): model = Post template_name = 'blog/index.html' context_object_name = 'post_list' def get_queryset(self): tag = get_object_or_404(Tag, pk=self.kwargs.get('pk')) return super(TagView, self).get_queryset().filter(tags=tag)
TagView繼承ListView:重設置model和tempale_name爲會致使 —— 通用視圖將查詢數據庫以獲取指定model(Post)的全部記錄,而後呈現位於/templates/blog/index.html的模板;而context_object_name重定義的意義在於 —— your own name for the list as a template variable;重寫get_queryset方法 —— 從數據庫中過濾出全部tag,將get_queryset方法添加到基於類的自定義視圖中,並指定order_by()。
這裏的get_object_or_404的功能在於若是找不到記錄,就引起Http404異常的快捷方式,見下面的例子:
def book_detail_view(request, primary_key): try: book = Book.objects.get(pk=primary_key) except Book.DoesNotExist: raise Http404('Book does not exist') return render(request, 'catalog/book_detail.html', context={'book': book}) 利用get_object_or_404來實現: from django.shortcuts import get_object_or_404 def book_detail_view(request, primary_key): book = get_object_or_404(Book, pk=primary_key) return render(request, 'catalog/book_detail.html', context={'book': book})
接下來的CategoryView、ArchivesView和TagView同樣,咱們重點看PostDetailView和IndexView:
class IndexView(ListView): model = Post template_name = 'blog/index.html' context_object_name = 'post_list' paginate_by = 10 def get_context_data(self, **kwargs): ... def pagination_data(self, paginator, page, is_paginated): ...
上面已經介紹:
等效於:
blog/views.py def index(request): post_list = Post.objects.all() return render(request, 'blog/index.html', context={'post_list': post_list})
而PostDetailView則繼承了DetailView,該模板用於從數據庫中取出一條記錄並渲染,其中model、template、context_object_name和ListView相似;這裏覆寫了get方法是爲了閱讀量加1的運算,同時注意到用super繼承了原來的response並返回;覆寫 get_object 方法的目的是由於須要對 post 的 body 值進行渲染;覆寫 get_context_data 的目的是由於除了將 post 傳遞給模板外(DetailView 已經幫咱們完成),還要把評論表單、post 下的評論列表傳遞給模板。
更詳細的操做你們能夠從GIT上獲取: https://github.com/zmrenwu/django-blog-tutorial
: 完~
: 你們以爲不錯,能夠點推薦給更多人~
[1]. 0二、PI3安裝openCV開發環境作圖像識別(詳細版)
[2]. 利用Django進行Web開發系列(一)
[3]. 博客園python web關鍵詞搜索
[4]. The Django Book
[5]. The Django Book - 第三章 視圖和URL配置
[6]. Built-in template tags and filters
[7]. The Django Book - 第五章 模型
[8]. Ubuntu下安裝MySQL及簡單操做
[9]. MySQL-python 1.2.5
[10]. 在Django中使用數據庫遇到的問題
[11]. Django manage.py Unknown command: 'syncdb'
[12]. The Django Book - 第六章 Django站點管理
[13]. Chapter 6: The Django Admin Site
[14]. The Django Book PDF
[15]. The Django Book - 第八章:高級視圖和URL配置
[16]. Django Tutorial Part 6: Generic list and detail views
[17]. 基於類的通用視圖:ListView 和 DetailView
@beautifulzzzz 智能硬件、物聯網,熱愛技術,關注產品 博客:http://blog.beautifulzzzz.com 園友交流羣:414948975