1. 程式人生 > >Django在OS X下的程式設計實戰(一)構建一個部落格系統

Django在OS X下的程式設計實戰(一)構建一個部落格系統

廢話少說,直奔主題,你要做事之前需要有一臺電腦,最好是Linux或者OS X,因為我在Macbook pro下工作,所以至少這裡的命令都在OS X下執行通過的。所有程式碼都是單獨一行方便你拷貝。Python程式碼會有>>>的提示,除此之前,沒有特別提示都是在命令列視窗進行,這裡也不去關心你的系統許可權問題,su或者sudo的事情,請自行搞定。

安裝Django,這裡是實戰,不會解釋太多架構和理論,邊做邊體會。

pip install Django==1.8.6

或者你和我一樣,用的Anaconda,那麼用下面的命令安裝

conda install Django

(可選操作)如果你是處女座,那麼希望在一個很乾淨的python環境下工作,那麼建立虛擬環境,這一部分不是Django的內容,程式碼放在這裡。

conda create --name myenv python=3

你會看到類似下面的螢幕輸出

Using Anaconda Cloud api site https://api.anaconda.org
Fetching package metadata .........
Solving package specifications: ..........

Package plan for installation in environment /Users/Winnerineast/anaconda/envs/myenv:

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    xz-5.2.2                   |                0         288 KB  conda-forge
    python-3.5.2               |                2        24.7 MB  conda-forge
    certifi-2016.8.2           |           py35_0         221 KB  conda-forge
    setuptools-25.1.6          |           py35_0         320 KB  conda-forge
    pip-8.1.2                  |           py35_0         1.6 MB  conda-forge
    ------------------------------------------------------------
                                           Total:        27.1 MB

The following NEW packages will be INSTALLED:

    ca-certificates: 2016.8.2-3      conda-forge
    certifi:         2016.8.2-py35_0 conda-forge
    ncurses:         5.9-8           conda-forge
    openssl:         1.0.2h-2        conda-forge
    pip:             8.1.2-py35_0    conda-forge
    python:          3.5.2-2         conda-forge
    readline:        6.2-0           conda-forge
    setuptools:      25.1.6-py35_0   conda-forge
    sqlite:          3.13.0-1        conda-forge
    tk:              8.5.19-0        conda-forge
    wheel:           0.29.0-py35_0   conda-forge
    xz:              5.2.2-0         conda-forge
    zlib:            1.2.8-3         conda-forge

Proceed ([y]/n)? y

Pruning fetched packages from the cache ...
Fetching packages ...
xz-5.2.2-0.tar 100% |##############################################################################################################################| Time: 0:00:02 104.66 kB/s
python-3.5.2-2 100% |##############################################################################################################################| Time: 0:00:22   1.17 MB/s
certifi-2016.8 100% |##############################################################################################################################| Time: 0:00:01 132.93 kB/s
setuptools-25. 100% |##############################################################################################################################| Time: 0:00:02 123.01 kB/s
pip-8.1.2-py35 100% |##############################################################################################################################| Time: 0:00:03 525.07 kB/s
Extracting packages ...
[      COMPLETE      ]|#################################################################################################################################################| 100%
Linking packages ...
[      COMPLETE      ]|#################################################################################################################################################| 100%
#
# To activate this environment, use:
# $ source activate myenv
#
# To deactivate this environment, use:
# $ source deactivate
#

這個命令將會建立一個單獨的完整python3執行環境,接下來輸入以下命令,啟用這個myenv虛擬環境:

source activate myenv

啟用之後的樣子如下,在命令列的提示符前面有一個括號,裡面顯示目前命令對那個python環境有效果。

(myenv) thismachine:~ home$ 

為了驗證Django是否安裝好,鍵入

python

進入python環境,然後使用以下程式碼確認Django的版本:

>>> import django
>>> django.VERSION
(1, 10, 0, 'final', 1)

建立你的第一個專案,Django提供了一些命令列工作,執行以下命令建立你的專案,注意一下,這個命令在哪個目錄下執行,就會在當前目錄生成專案,所以你如果需要在特定的目錄建立專案,請先切換當前目錄為那個目錄:

django-admin startproject mysite


這個專案的目錄結構如下:

mysite/

manage。py

mysite/

__init__.py

settings.py

urls.py

wsgi.py

這個專案的具體含義,我們隨著程式設計的深入逐步展開,這裡就不展開講解了。接下來,需要初始化這個專案的資料庫資料,執行以下程式碼:

(myenv) thismachine:~ home$ cd mysite
(myenv) thismachine home$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK

執行一個開發伺服器,請使用以下程式碼:
(myenv) thismachine:mysite home$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
August 25, 2016 - 07:44:57
Django version 1.10, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
很容易,你可以聯想到下面的一些定製命令,比如在特定IP和埠執行這個專案:

python manage.pyrun server127.0.0.1:8001 --settings=mysite.settings

接下來,需要在這個伺服器上建立自己的程式,請使用以下命令:

python manage.py startapp blog

生成的程式碼結構如下:

blog/

__init__.py

admin.py

migrations/

__init__.py

models.py

tests.py

views.py

不解釋細節,就是一套模版生成的,每個檔案的價值,在接下來的定製過程中一一介紹。

萬變不離其宗,所有程式的核心就是處理資料,所以我們首先需要定義和初始化資料,換句話就是模型。在Django框架裡面,已經抽象了模型,參見django.db.models.Model。所以的資料模型都是從這個起始的。

讓我們來看blog的模型程式碼吧。以下程式碼都是在models.py中修改和增加的,如果你習慣了用IDE,推薦你用PyCharm(具體安裝和使用PyCharm的文章,我會單獨寫)。

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User

class Post(models.Model):
    STATUS_CHOICES = (
        ('draft','Draft'),
        ('published','Published'),
    )
    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250,
                            unique_for_date='publish')
    author = models.ForeignKey(User,
                               related_name='blog_posts')
    body = models.TextField()
    publish = models.DateTimeField(default=timezone.now)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=10,
                              choices=STATUS_CHOICES,
                              default='draft')

    class Meta:
        ordering = ('-publish',)

    def __str__(self):
        return self.title

以上的這些資料模型定義和資料庫欄位定義是相仿的,只是語法不一樣,具體和全部的模型定義,請參見這裡點選開啟連結

為了能夠讓Django可以按照模型定義建立資料庫裡面的表格,我們需要在settings.py裡面增添:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles','blog'<span style="font-family: Arial, Helvetica, sans-serif;">	</span>
]

這樣,就能在資料庫建立blog的相關表和欄位。接下來需要命令列去掃描settings內容來建立blog。
(myenv) thismachine:mysite home$ python manage.py makemigrations blog
Migrations for 'blog':
  blog/migrations/0001_initial.py:
    - Create model Post

這個命令在blog/migration下面生成一個針對資料庫的0001_initial.py,它的內容可以通過這個看到:
(myenv) thismachine:mysite home$ python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Post
--
CREATE TABLE "blog_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(250) NOT NULL, "slug" varchar(250) NOT NULL, "body" text NOT NULL, "publish" datetime NOT NULL, "created" datetime NOT NULL, "updated" datetime NOT NULL, "status" varchar(10) NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id"));
CREATE INDEX "blog_post_2dbcba41" ON "blog_post" ("slug");
CREATE INDEX "blog_post_4f331e2f" ON "blog_post" ("author_id");
COMMIT;

執行遷移指令,建立表格:
(myenv) thismachine:mysite home$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
  Rendering model states... DONE
  Applying blog.0001_initial... OK

接下來,我們需要建立一個超級使用者,然後在這個使用者之下,再展開其他使用者和操作:
(myenv) WMBP:mysite Winnerineast$ python manage.py createsuperuser
Username (leave blank to use 'winnerineast'): admin
Email address: [email protected]
Password: 
Password (again): 
Superuser created successfully.

這個時候,再執行這個站點,當你開啟http://localhost:8000/admin的時候,需要輸入使用者名稱和密碼。進去之後就是標準的使用者管理介面,按照慣例部落格的方法,在圖形介面下管理部落格使用者。目前,只看得到Group和Users,我們現在把blog模型加進來,這就需要在admin.py裡面註冊:
from django.contrib import admin
from .models import Post
# Register your models here.
admin.site.register(Post)
奇妙的是,不需要重啟伺服器,直接儲存admin.py,重新整理瀏覽器,在管理介面就出現了Blog。這樣,你可以直接在管理介面直接增加部落格的帖子。你看到了admin.py就是控制管理介面的設定,如果要定製帖子建立選項,那麼改這個檔案吧,以下是我們定製化的程式碼:
from django.contrib import admin
from .models import Post

class PostAdmin(admin.ModelAdmin):
    list_display = ('title','slug','author','publish',
                    'status')
    list_filter = ('status','created','publish','author')
    search_fields = ('title','body')
    prepopulated_fields = {'slug': ('title',)}
    raw_id_fields = ('author',)
    date_hierarchy = 'publish'
    ordering = ['status','publish']

admin.site.register(Post,PostAdmin)

如此往復,改一點程式碼,重新整理一下瀏覽器,多試試就都明白了。架構了資料模型,接下來就是用API對於資料進行操作,下面通過python命令列介面開啟一個對站點資料進行操作的介面。

(myenv) thismachine:mysite home$ python manage.py shell
Python 3.5.2 | packaged by conda-forge | (default, Jul 26 2016, 01:37:38) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth.models import User
>>> from blog.models import Post
>>> user = User.objects.get(username='admin')
>>> Post.objects.create(title='One more post',
... slug='one-more-post',
... body='Post today',
... author=user)
<Post: One more post>
Post.save()

更多操作可以參見Django的線上文件。