django從0到1搭建網站

曾經有人說我前端很水,那麼在這一系列文章中我打算把先後端融合在一塊兒來作一次網站的全面重構,但願能夠把剛剛入行的同窗帶上正途php

 

請尊重原創,轉載請註明來源網站www.shareditor.com以及原始連接地址html

聊聊工程

現在,數據科學家已經逐漸取代如今的「軟件工程師」成爲IT行業的主流職業,和「全民都在聊人工智能」同樣,可能所有IT工做者都要每天研究算法、琢磨模型、跑數據、調參數、跑數據、調參數,那些被淘汰的「軟件工程師」會真的成爲民工同樣的行業,可是我以爲任何算法都離不開工程實現,再好的模型沒有底層架構的支撐和上層產品應用的展示也沒法發揮做用,因此對於一個技術人士,不擅長工程終難把能力發揮到極致。隨着中國和國外前沿科技的接軌,未來必定是小創業團隊成爲主流,一個小創業團隊更喜歡算法+工程的全能型人才,跟着我一塊兒學習進步,你未來也許就會是其中一個。前端

 

聊聊重構

提及重構,不少人都有感慨,由於只有當遇到比較大的問題的時候纔會考慮重構,好比技術人員流動大致使代碼中風格百出,百花齊放,無用代碼一大堆不敢刪,奇葩邏輯遍地皆是卻沒有一行註釋、一篇文檔。在這種無奈狀況下,咱們不得已選擇了重構,寄但願於解決全部問題,但每每代價比收益高出一個數量級,不少人由於重構被迫出局。但重構這件事情是一件必經之路,任何一個產品從誕生到成熟都會經歷幾回重構,由於沒有人能在最初的時候就預示到最終的邏輯(若是能預示那何須有最初呢),就算像BAT這樣成熟的公司,他們內部的系統也是平均兩年作一次重構。回過頭來講一下個人網站重構的初衷:1)我也是不斷成長的,做爲一個想作全棧的工程師來講,新思路總想去嘗試;2)不少關注個人網友以爲我以前寫的教程總有意猶未盡的感受,但願能深刻寫一點;3)php終究不是世界上最好的語言(此處可能引起戰爭),用來用去以爲仍是遷移python爲好,也和咱們的機器學習知識作個融合;python

 

技術棧選擇

首先說語言。我曾經說過,語言只是工具,每門語言都有它存在的理由,它擅長用在什麼地方就用在什麼地方,不擅長的不要勉強,不歧視、不在一棵樹上吊死、哪一個行就上哪一個。後端語言我選擇python,由於python是社區最活躍的語種之一且呈上升趨勢,另外也是大數據與人工智能方向的主流語言。web框架我選擇django,由於它更專業更強大,擴展性強,社區也更活躍。前端框架我選擇直接用django模板渲染,沒有選擇angular等前端框架,由於seo不友好mysql

 

服務端容器選擇

在tomcat、apache httpd、nginx等web服務器下游,須要部署python的應用服務器容器,我選擇uwsgi,它相似於nginx,經過一個守護進程把不一樣的http請求轉交給子進程併發處理,而且支持多線程的方式,性能較高,更重要的,django會自動幫咱們生成wsgi的配置,自然對uwsgi友好nginx

 

總結

開篇就講這麼多,主要仍是得看後面個人重構過程,咳咳!出發!git

http://www.shareditor.com/blogshow/?blogId=126github

安裝開發和運行的基本環境

首先,python是必須的,咱們選擇python2.7,沒有安裝能夠根據不一樣的操做系統安裝,若是是rhel或centos能夠用yum  install python,若是是ubuntu能夠用apt-get install python,若是是mac能夠用brew install python,若是以上都不行能夠直接下官方包安裝(https://www.python.org/downloads/)web

而後,安裝django相關組件(當前最新版是1.11):算法

pip install django

安裝web容器:

pip install uwsgi

小技巧:若是使用pip install安裝庫比較慢,能夠用豆瓣的鏡像,方法相似下面:

pip install django -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

 

建立開源代碼庫

在github中建立倉庫shareditor,並在本地建立空倉庫提交

github庫在:https://github.com/warmheartli/shareditor

本地倉庫以下:

[lichuang@localhost:~/Developer/shareditor $] ls README.md [lichuang@localhost:~/Developer/shareditor $] pwd /Users/lichuang/Developer/shareditor

 

建立django工程

在安裝django時已經自動幫咱們安裝了django-admin工具,執行以下命令自動建立一個完整的工程目錄(其中最後一個參數是工程目錄,倒數第二個參數是工程名):

django-admin startproject shareditor /Users/lichuang/Developer/shareditor

這時可以找到自動建立的manage.py文件(一個工具腳本,不須要修改),和工程總目錄shareditor(裏面包含了配置文件settings.py、總路由配置urls.py、wsgi協議配置文件wsgi.py)

下面咱們在這個工程裏建立咱們網站app:

django-admin startapp web

咱們看到它自動建立了web目錄,而且自動幫咱們組織了一些文件,包括:

admin.py:數據庫表的後臺管理類通常定義在這裏

apps.py:這個app的配置信息,這個文件通常不動

migrations目錄:存儲數據庫遷移相關的臨時文件,不須要動

models.py:和數據庫對應的model類通常定義在這裏

tests.py:自動化腳本

views.py:視圖層腳本,我通常會把控制邏輯寫到這裏

這些文件全都看不懂也沒有關係,到如今爲止,咱們的網站已經能夠運行了,執行:

python manage.py runserver

咱們能夠看到一些提示,直接訪問http://127.0.0.1:8000/就能夠訪問網頁了,以下:

上面的頁面是django展現的默認頁面,下面咱們稍做修改來看看django框架是怎麼按照咱們的指示工做的

 

helloworld

修改web/views.py,增長以下函數:

from django.http import HttpResponse def index(request): return HttpResponse('Hello World!')

這僅僅是定義一個函數,然並卵

請尊重原創,轉載請註明來源網站www.shareditor.com以及原始連接地址

咱們來修改一下咱們的路由規則,修改shareditor/urls.py,把內容改爲:

from web import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^$', views.index) ]

下面咱們從新執行python manage.py runserver,並打開瀏覽器看看是否是看到了高大上的Hello World!

 

讓網站更專業

上面執行的python manage.py runserver實際上只是django的一個用於開發和調試的方法,它只是一個進程一個線程在運行,沒法支持網站的高併發訪問,下面咱們介紹一下如何部署一個專業的網站。

首先咱們配置好咱們的web容器,在shareditor目錄下建立uwsgi.ini,內容以下:

[uwsgi] chdir = /Users/lichuang/Developer/shareditor http = 127.0.0.1:8080 http-keepalive = 1 module = shareditor.wsgi:application master = true processes = 4 daemonize = /Users/lichuang/Developer/shareditor/logs/uwsgi.log disable-logging = 1 buffer-size = 16384 harakiri = 5 post-buffering = 8192 post-buffering-bufsize = 65536 pidfile = /Users/lichuang/Developer/shareditor/logs/uwsgi.pid enable-threads = true single-interpreter = true

這裏的目錄要隨着你部署的目錄作相應修改

由於logs目錄還不存在,因此咱們手工mkdir建立一個

下面執行啓動命令:

uwsgi --ini shareditor/uwsgi.ini

這時咱們能夠查看一下logs/uwsgi.log文件,若是沒有異常信息說明網站已經部署成功了,咱們ps ux|grep uwsgi看一下進程:

lichuang 13390   0.4  0.0  2425088    300 s004  S+   10:19下午   0:00.00 grep --color uwsgi lichuang 13307 0.0 0.0 2491336 924 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13306 0.0 0.0 2491336 2540 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13305 0.0 0.0 2491336 2520 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini lichuang 13304 0.0 0.0 2491336 2484 ?? S 10:18下午 0:00.00 uwsgi --ini shareditor/uwsgi.ini

能夠看到啓動了4個進程,其中一個守護進程用來接收和分發請求,3個子進程(對應配置文件裏的processes = 4)用來處理請求

這時咱們打開瀏覽器訪問:http://127.0.0.1:8080/又能看到Hello World!了

 

高可用性部署(新手可略過)

另外爲了讓咱們的網站具備高可用性(高可用就是掛掉一臺機器不影響服務),一臺機器啓動服務還不行,咱們至少要部署兩臺徹底對等的web服務來同時提供服務,那麼用戶在瀏覽器裏訪問時到底訪問的是哪一個機器呢?這裏有兩種實現方案,一種是配置DNS記錄,同一個域名對應多個ip,那麼當一個ip不可用時瀏覽器會自動嘗試另外的ip,還有一種方法就是經過穩定的代理服務器(如nginx、apache httpd等)來配置成一個負載均衡代理,對外暴露的一個ip,對內鏈接到多臺web服務器

http://www.shareditor.com/blogshow/?blogId=127

建立和連接數據庫

首先,咱們須要有一個mysql的服務,你能夠選擇本身安裝啓動一個mysql服務,我選擇了阿里雲的雲數據庫RDS(和本地搭建沒有區別,收費但不貴),我建立了一個數據庫名叫db_shareditor(若是本地搭建的mysql,執行命令是create database db_shareditor)

下面咱們配置咱們的網站工程來鏈接這個數據庫,修改shareditor/settings.py裏的DATABASE改爲以下:

DATABASES = {
    'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_shareditor', 'USER': 'username', 'PASSWORD': 'password', 'HOST': 'hostip', 'PORT': '3306', 'OPTIONS': { 'sql_mode': 'traditional', } } }

這裏的USER、PASSWORD、HOST、PORT都配置成你本身的,而後咱們來檢測一下數據庫配置是否正確

[lichuang@localhost:~/Developer/shareditor $] python manage.py check System check identified no issues (0 silenced).

看到這樣的信息說明咱們的配置沒有問題,不然會拋出異常,這時咱們根據異常信息再追查問題

 

建立model並自動生成數據庫表

這裏解釋一下什麼是model,model就是數據庫表在內存裏的數據結構,好比某個數據庫表有A和B兩個字段,那麼它對應的model通常也會寫成A和B兩個成員,這樣咱們在代碼裏操做model的實例就是在操做數據庫

每一個model的設計都須要精心打磨,咱們首先建立一個BlogPost的model,修改web/models.py,增長以下類定義:

class BlogPost(models.Model): title = models.CharField(max_length=255, verbose_name='文章標題') body = models.TextField(verbose_name='文章內容') create_time = models.DateTimeField(verbose_name='建立時間')

這個類實際上定義了一個數據庫的結構,下面咱們用django工具來自動根據這個結構定義生成對應的數據庫表,執行:

python manage.py migrate

這時咱們再看一下數據庫多出了這些數據庫表

auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permission
django_admin_log
django_content_type django_migrations django_session

這裏比較奇怪的是怎麼多出了這麼一批數據而沒有找到咱們的blogpost呢?這是由於settings.py裏的INSTALLED_APPS默認安裝了一些其餘的玩意,而並無安裝咱們的web這款app,好,那如今咱們暫時先保留默認安裝的app(之後有用),把咱們的web添加進去,以下:

INSTALLED_APPS = [
    'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes' 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'web', ]

如今咱們從新生成migrate文件並建立數據庫表,執行:

python manage.py makemigrations
python manage.py migrate

這時再看數據庫表多出了web_blogpost(django會自動用app名字小寫加下劃線加model名的小寫來做爲數據庫表的名字,實際上數據庫表名咱們也是能夠本身來配置的,感興趣本身google一下吧)

 

建立有關聯關係的數據庫表

咱們的每篇文章都會有一個類別(subject,如大數據、全棧技術等),每一個類別會對應多篇文章,也就是1對多的關係,那麼咱們能夠利用django的models裏的外鍵類型來關聯,以下:

class Subject(models.Model): name = models.CharField(max_length=255, verbose_name='類別名稱') introduce = models.CharField(max_length=255, verbose_name='類別簡介') image = models.ImageField(verbose_name='類別圖片') class BlogPost(models.Model): title = models.CharField(max_length=255, verbose_name='文章標題') body = models.TextField(verbose_name='文章內容') create_time = models.DateTimeField(verbose_name='建立時間') subject = models.ForeignKey(Subject, verbose_name='類別', null=True)

咱們從新執行:

python manage.py makemigrations
python manage.py migrate

這時再看數據庫表多出了web_subject,同時web_blogpost也自動多出了一個subject_id字段

有人問了,這用不用外鍵有什麼關係呢,手工寫好一個subject_id字段,而後在代碼邏輯裏就把這個字段做爲查詢subject表的key不就好了嗎?看來該是介紹IDE的時候了,我來給你們介紹一款棒棒的開發工具PyCharm,具體安裝方法本身去百度,我如今裝的是PyCharm 2017.1.4版本,記得必定要配置好Project Interpreter爲系統裏安裝好django的那個python環境

下面見證奇蹟的時刻到了,用PyCharm打開咱們上面的shareditor工程,並打開views.py文件,咱們來編輯以下一段代碼:

個人天啊!好強大有木有!當咱們輸入幾個字母前綴的時候,它會把咱們用外鍵關聯的類的各類方法都給咱們列出來,不再用苦逼的查文檔了

 

建立多對多關係的數據庫表

咱們的每篇文章都會有多個標籤(tag, 如:從0到1搭建我的網站、本身動手作聊天機器人等),每一個標籤會對應多篇文章,也就是多對多的關係,那麼咱們能夠利用django的models裏的ManyToMany類型來關聯,咱們添加Tag類以下:

class Tag(models.Model): name = models.CharField(max_length=255, verbose_name='標籤名稱')

併爲BlogPost類添加以下成員:

tags = models.ManyToManyField(Tag, verbose_name='標籤')

咱們從新執行:

python manage.py makemigrations
python manage.py migrate

這時再看數據庫表多出了web_tag和web_blogpost_tag兩個表,這裏的web_blogpost_tag其實是一個關係表,也就是說,BlogPost類多了tags成員,但web_blogpost表裏並無多任何字段,但當咱們在PyCharm中輸入tags前綴的時候依然會看到相關提示

 

總結

這一節咱們介紹了數據庫表和model之間的關係,以及一對多、多對多關係的使用,下一節咱們來繼續討論利用model對數據庫作讀寫

http://www.shareditor.com/blogshow/?blogId=128

django-admin的帳戶管理

當咱們直接打開http://127.0.0.1:8000/admin時,雖然可以看到管理後臺登錄界面,可是咱們沒有帳號密碼是沒法登錄的,須要咱們初始化一個超級用戶,那麼方法如何呢?咱們能夠經過執行python manager.py輸出的提示來找到createsuperuser這個命令,執行:

python manage.py createsuperuser

按照提示輸入帳號、郵箱、密碼,而後再次進入http://127.0.0.1:8000/admin就能夠登錄了

登錄進入後咱們看到了Group和Users兩個管理項,這實際上對應着數據庫裏的auth_group和auth_user表,在Users裏能看到咱們剛剛建立的超級用戶,在這裏咱們能夠添加新的用戶,併爲不一樣用戶配置不一樣權限

 

配置admin管理數據庫

還記得上一節咱們建立的三個Model及其數據庫表嗎?BlogPost、Subject、Tag,那麼怎麼才能在django-admin管理後臺管理這三個表的內容呢?

修改web/admin.py,添加以下內容:

from django.contrib import admin from .models import BlogPost class BlogPostAdmin(admin.ModelAdmin): list_display = ('title', 'create_time', 'subject', 'tags') admin.site.register(BlogPost, BlogPostAdmin)

從新登錄http://127.0.0.1:8000/admin管理頁面,咱們看到:

點進去能夠看到文章的管理頁面,由於咱們在BlogPost這個model裏設置的subject和tags字段不能夠爲空,所以咱們須要提早添加類別和標籤,下面咱們再完善一下Subject和Tags的管理類,以下:

class SubjectAdmin(admin.ModelAdmin): list_display = ('name',) class TagAdmin(admin.ModelAdmin): list_display = ('name',) admin.site.register(Subject, SubjectAdmin) admin.site.register(Tag, TagAdmin)

這時咱們再嘗試在管理頁面新建一個Subject、一個Tag、一個BlogPost吧,建好以後能夠在後臺數據庫直接查看到數據已經寫到了數據庫中

 

管理界面的定製化

愛漂亮的同窗可能會發現後臺管理界面還不夠漂亮和友好,好比頁面頂部寫的「Django administrator」能不能換成「SharEDITor管理後臺」,好比管理首頁裏的「WEB」能不能改爲「網站」,「Blog posts」能不能改爲「文章」,另外咱們在新建BlogPost的時候,類別和標籤這兩項裏寫的是「Subject object」和"Tag object",都不知道具體信息,下面咱們來各個擊破作一下定製

首先咱們修改web/models.py,爲Subject類添加以下成員:

class Meta: verbose_name_plural = '類別' def __unicode__(self): return self.name

再爲Tag類添加以下成員:

class Meta: verbose_name_plural = '標籤' def __unicode__(self): return self.name

再爲BlogPost類添加以下成員:

class Meta: verbose_name_plural = '文章' def __unicode__(self): return self.title

解釋一下,這裏的verbose_name_plural就是在這個結構在管理頁面裏的展現名稱,__unicode__就是這個結構裏每個對象的展現形式,不用多說,直接看一下你的管理頁面的效果就知道了

管理頁面總標題由於是django-admin自身的內容,所以作定製有些複雜些,此處新手能夠略過

請尊重原創,轉載請註明來源網站www.shareditor.com以及原始連接地址

在根目錄下建立以下目錄templates/admin,並新建base_site.html文件,內容以下:

{% extends "admin/base.html" %} {% load i18n %} {% block title %}{{ title }} | {% trans 'SharEDITor後臺管理' %}{% endblock %} {% block branding %} <h1 id="site-name">{% trans 'SharEDITor後臺管理' %}</h1> {% endblock %} {% block nav-global %}{% endblock %}

修改shareditor/settings.py文件,在TEMPLATES  =>  DIRS配置項中添加'templates',這樣就能夠自動找到模板目錄了,實際上這裏的admin/base_site.html是重寫了django-admin的源碼。從新打開後臺管理界面看下效果吧

 

圖片管理(高級內容,新手略過)

咱們在新建一個類別的時候要爲image字段選擇一張圖片,咱們看到圖片實際上上傳到了根目錄下。這種方式存在一些問題:1)若是要在網站中展現這張圖片須要爲其單獨指定路由;2)若是網站多機部署沒法實時同步數據;3)若是圖片很大,會耗費不少帶寬,響應慢

爲了解決如上問題,咱們引入阿里雲的對象存儲OSS服務(收費,但不貴,這裏不是幫阿里雲打廣告,可是阿里雲確實作的比較好),它的優勢是有CDN加速,也就是不一樣地域都有鏡像,訪問快,並且價格低廉,可比一樣的網絡帶寬便宜多了

OSS的使用請見官方文檔,我這裏直接貼代碼,懂的能夠參考,不懂的能夠直接用

首先要在阿里雲的OSS中建立一個Bucket,如shareditor-shareditor,讀寫權限必定要選擇「公共讀」

其次要安裝oss2庫,執行:

pip install oss2

而後在咱們代碼的根目錄建立commons目錄(用於放置全部公共組件),並在其中建立一個空的__init__.py(做爲lib的目錄都要有這個文件,不然沒法import),並建立ossutils.py文件,內容以下:

# -*- coding: utf-8 -*- import oss2 import time AccessKeyId = '你的AccessKey' AccessKeySecret = '你的AccessKey密碼' Endpoint = 'oss-cn-beijing.aliyuncs.com' InternalEndpoint = 'oss-cn-beijing-internal.aliyuncs.com' def upload_oss(bucket_name, file_name, bytes_content): """ :param bucket_suffix: 區分測試環境和線上環境 :param file_name: 會自動添加時間戳 :param bytes_content: 二進制的文件內容 :return: 外網能夠訪問的url """ auth = oss2.Auth(AccessKeyId, AccessKeySecret) bucket = oss2.Bucket(auth, Endpoint, bucket_name) file_path = 'dynamic/' + str(int(time.time())) + '_' + file_name result = bucket.put_object(file_path, bytes_content) if result.status == 200: return 'http://' + bucket_name + '.oss-cn-beijing.aliyuncs.com/' + file_path else: return None

下面咱們重載Subject的image的上傳邏輯,修改web/admin.py,引入ossuitls:

from commons.ossutils import upload_oss

聲明BucketName變量下面會用到:

BucketName = 'shareditor-shareditor'

修改SubjectAdmin類,添加以下方法:

def save_model(self, request, obj, form, change): if 'image' in request.FILES: image_name = request.FILES['image'].name image_content = request.FILES['image'].read() url = upload_oss(BucketName, image_name, image_content) if url: obj.image = url super(SubjectAdmin, self).save_model(request, obj, form, change)

這時咱們從新修改一個類目,從新上傳圖片,咱們發現圖片已經再也不保存到本地文件了,而在阿里雲的OSS裏找到了上傳的文件,而在咱們的數據庫裏存儲了這個圖片在阿里雲OSS中的url,能夠直接訪問

 

總結

有關admin管理後臺的內容以上這些基本夠用了,剩下的就是根據你的業務邏輯去設計本身的表結構,發揮自身的主動性啦

 

http://www.shareditor.com/blogshow/?blogId=129

相關文章
相關標籤/搜索