溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python全棧開發(fā)之Django進階

發(fā)布時間:2020-08-24 09:05:17 來源:網(wǎng)絡 閱讀:4326 作者:灰白世界 欄目:編程語言

No.1 靜態(tài)文件處理

項目中CSS、JS、圖片都屬于靜態(tài)文件,一般會將靜態(tài)文件存到一個單獨目錄中,便于管理,在HTML頁面調(diào)用時,需要指定靜態(tài)文件的路徑,Django提供了一種解析靜態(tài)文件的機制,文件可以放在項目目錄下,也可以放在應用目錄下

在mysite/setting.py設置文件的物理路徑

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

在static目錄下創(chuàng)建css、js、img目錄

No.2 中間件

Django的中間件是一個輕量級的插件系統(tǒng),可以介入請求和響應的過程,修改輸入與輸出,中間件的設計為開發(fā)者提供了一種無侵入式的開發(fā)方式,增加了框架的健壯性,Django在中間價中內(nèi)置了5個方法,區(qū)別在于不同的階段執(zhí)行,用來干預請求和響應

初始化,不需要參數(shù),服務器響應第一個請求的時候調(diào)用一次,用于確定是否啟用中間件

def __init__(self):
    pass

處理請求前 每個請求上,生成request對象后,配置url前調(diào)用,返回None或HttpResponse對象

def process_request(self, request):
    pass

處理視圖前 在每個請求上,url匹配后,視圖函數(shù)調(diào)用之前調(diào)用,返回None或HttpResponse對象

def process_view(self, request, view_func, *view_args, **view_kwargs):
    pass

處理響應后 視圖函數(shù)調(diào)用之后,所有響應返回瀏覽器之前調(diào)用,返回一個HttpResponse對象

def process_response(self, request, response):
    pass

異常處理:當視圖拋出異常時調(diào)用,在每個請求上調(diào)用,返回一個HttpResponse對象

def process_exception(self, request,exception):
    pass

栗子

# app01/middware.py
class my_mid:
    def __init__(self):
        print('--------------init')

    def process_request(self,request):
        print('--------------request')

    def process_view(self,request, view_func, *view_args, **view_kwargs):
        print('--------------view')

    def process_response(self,request, response):
        print('--------------response')
        return response

class exp1:
    def process_exception(self,request,exception):
        print('--------------exp1')

class exp2:
    def process_exception(self,request,exception):
        print('--------------exp2')

# mysite/setting.py
MIDDLEWARE_CLASSES = [
    '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',
    'app01.middleware.my_mid',
]

No.3 分頁

Django提供了數(shù)據(jù)分頁的類,這些類被定義在django/core/paginator.py中, 類Paginator用于對列進行一頁n條數(shù)據(jù)的分頁運算,類Page用于表示第m頁的數(shù)據(jù)

Paginator類實例對象

  • 方法init(列表,int):返回分頁對象,第一個參數(shù)為列表數(shù)據(jù),第二個參數(shù)為每頁數(shù)據(jù)的條數(shù)
  • 屬性count:返回對象總數(shù)
  • 屬性num_pages:返回頁面總數(shù)
  • 屬性page_range:返回頁碼列表,從1開始,例如[1, 2, 3, 4]
  • 方法page(m):返回Page類實例對象,表示第m頁的數(shù)據(jù),下標以1開始

Page類實例對象

  • 調(diào)用Paginator對象的page()方法返回Page對象,不需要手動構(gòu)造。
  • 屬性object_list:返回當前頁對象的列表。
  • 屬性number:返回當前是第幾頁,從1開始。
  • 屬性paginator:當前頁對應的Paginator對象。
  • 方法has_next():如果有下一頁返回True。
  • 方法has_previous():如果有上一頁返回True。
  • 方法len():返回當前頁面對象的個數(shù)。

栗子

from django.core.paginator import Paginator
from app01.models import AreaInfo

# 參數(shù)pIndex表示:當前要顯示的頁碼
def page_test(request,pIndex=1):
    #查詢所有的地區(qū)信息
    list_address = AreaInfo.objects.filter(aParent__isnull=True)
    #將地區(qū)信息按一頁10條進行分頁
    p = Paginator(list_address, 10)
    # 通過url匹配的參數(shù)都是字符串類型,轉(zhuǎn)換成int類型
    pIndex = int(pIndex)
    # 獲取第pIndex頁的數(shù)據(jù)
    page_list = p.page(pIndex)
    #獲取所有的頁碼信息
    plist = p.page_range
    #將當前頁碼、當前頁的數(shù)據(jù)、頁碼信息傳遞到模板中
    return render(request, 'app01/page_test.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})
 # app01/urls.py
 url(r'^page(?P<pIndex>[0-9]*)/$', views.page_test),
 # app01/views.py
<html>
    <head>
        <title>分頁</title>
    </head>
    <body>
        顯示當前頁的地區(qū)信息:<br>
        <ul>
            {%for area in list%}
                <li>{{area.id}}--{{area.atitle}}</li>
            {%endfor%}
        </ul>
        <hr>
        顯示頁碼信息:當前頁碼沒有鏈接,其它頁碼有鏈接<br>
        {%for pindex in plist%}
            {%if pIndex == pindex%}
                {{pindex}}??
            {%else%}
                <a href="/page{{pindex}}/">{{pindex}}</a>??
            {%endif%}
        {%endfor%}
    </body>
</html>

No.4 富文本編輯器

借助富文本編輯器,網(wǎng)站的編輯人員能夠像使用offfice一樣編寫出漂亮的、所見即所得的頁面

富文本編輯器

安裝

pip3 install django-tinymce

栗子

在mysite/setting.py添加應用
INSTALLED_APPS = (
    ...
    'tinymce',
)
在mysite/setting.py配置編輯器
TINYMCE_DEFAULT_CONFIG = {
    'theme': 'advanced',
    'width': 600,
    'height': 400,
}
在app01/urls.py配置url
urlpatterns = [
    ...
    url(r'^tinymce/', include('tinymce.urls')),
]

在admin中定義使用

在app01/models.py中定義模型類

from django.db import models
from tinymce.models import HTMLField

class GoodsInfo(models.Model):
    gcontent=HTMLField()

執(zhí)行遷移
在admin中進行注冊

自定義使用

在app01/views.py中定義視圖

def editor(request):
    return render(request, 'app01/editor.html')
在app01/urls.py定義url
url(r'^editor/',views.editor),

在項目目錄下創(chuàng)建cs、js、img目錄
打開py_django目錄,找到tinymce是的目錄

/home/python/.virtualenvs/py_django/lib/python3.5/site-packages/tinymce/static/tiny_mce

拷貝tiny_mce_src.js文件、langs文件夾以及themes文件夾拷貝到項目目錄下的static/js/目錄下

配置靜態(tài)文件查找路徑

創(chuàng)建editor.html模板

<html>
<head>
    <title>自定義使用tinymce</title>
    <script type="text/javascript" src='/static/js/tiny_mce.js'></script>
    <script type="text/javascript">
        tinyMCE.init({
            'mode':'textareas',
            'theme':'advanced',
            'width':400,
            'height':100
        });
    </script>
</head>
<body>
<form method="post" action="#">
    <textarea name='gcontent'>哈哈,這是啥呀</textarea>
</form>
</body>
</html>

No.5 全文檢索

全文檢索不同于特定字段的模糊查詢,使用全文檢索的效率更高,并且能夠?qū)τ谥形倪M行分詞處理

  • haystack:全文檢索的框架,支持whoosh、solr、Xapian、Elasticsearc四種全文檢索引擎,點擊查看
  • whoosh:純Python編寫的全文搜索引擎,雖然性能比不上sphinx、xapian、Elasticsearc等,但是無二進制包,程序不會莫名其妙的崩潰,對于小型的站點,whoosh已經(jīng)足夠使用,點擊查看
  • jieba:一款免費的中文分詞包,如果覺得不好用可以使用一些收費產(chǎn)品。

全文檢索

安裝包

pip install django-haystack
pip install whoosh
pip install jieba

修改app01/settings.py文件,安裝應用haystack

INSTALLED_APPS = (
    ...
    'haystack',
)

在app01/settings.py文件中配置搜索引擎

HAYSTACK_CONNECTIONS = {
    'default': {
        #使用whoosh引擎
        'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
        #索引文件路徑
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    }
}

#當添加、修改、刪除數(shù)據(jù)時,自動生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

在app01/urls.py中添加搜索的配置

url(r'^search/', include('haystack.urls')),

創(chuàng)建索引及引擎

在app01下創(chuàng)建search_indexs.py文件

from haystack import indexes
from app01.models import GoodsInfo
#指定對于某個類的某些數(shù)據(jù)建立索引
class GoodsInfoIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        return GoodsInfo

    def index_queryset(self, using=None):
        return self.get_model().objects.all()

在templates目錄下創(chuàng)建search/indexes/app01/目錄

在上面的目錄中創(chuàng)建"goodsinfo_text.txt"文件

{{object.gcontent}}

找到虛擬環(huán)境py_django下的haystack目錄

/home/python/.virtualenvs/py_django/lib/python3.5/site-packages/haystack/backends/

在上面的目錄中創(chuàng)建ChineseAnalyzer.py文件

import jieba
from whoosh.analysis import Tokenizer, Token

class ChineseTokenizer(Tokenizer):
    def __call__(self, value, positions=False, chars=False,
                 keeporiginal=False, removestops=True,
                 start_pos=0, start_char=0, mode='', **kwargs):
        t = Token(positions, chars, removestops=removestops, mode=mode,
                  **kwargs)
        seglist = jieba.cut(value, cut_all=True)
        for w in seglist:
            t.original = t.text = w
            t.boost = 1.0
            if positions:
                t.pos = start_pos + value.find(w)
            if chars:
                t.startchar = start_char + value.find(w)
                t.endchar = start_char + value.find(w) + len(w)
            yield t

def ChineseAnalyzer():
    return ChineseTokenizer()

復制whoosh_backend.py文件,改為如下名稱

whoosh_cn_backend.py

打開復制出來的新文件,引入中文分析類,內(nèi)部采用jieba分詞

from .ChineseAnalyzer import ChineseAnalyzer

更改詞語分析類

查找
analyzer=StemmingAnalyzer()
改為
analyzer=ChineseAnalyzer()

初始化索引數(shù)據(jù)

python manage.py rebuild_index

按提示輸入y后回車,生成索引

使用

按照配置,在admin管理中添加數(shù)據(jù)后,會自動為數(shù)據(jù)創(chuàng)建索引,可以直接進行搜索,可以先創(chuàng)建一些測試數(shù)據(jù)

在app01/views.py中定義視圖query

def query(request):
    return render(request,'app01/query.html')

在app01/urls.py中配置

url(r'^query/', views.query),

在templates/app01/目錄中創(chuàng)建模板query.html

<html>
<head>
    <title>全文檢索</title>
</head>
<body>
<form method='get' action="/search/" target="_blank">
    <input type="text" name="q">
    <br>
    <input type="submit" value="查詢">
</form>
</body>
</html>

自定義搜索結(jié)果模板:在templates/search/目錄下創(chuàng)建search.html

搜索結(jié)果進行分頁,視圖向模板中傳遞的上下文如下:

  • query:搜索關(guān)鍵字
  • page:當前頁的page對象
  • paginator:分頁paginator對象

視圖接收的參數(shù)如下:

  • 參數(shù)q表示搜索內(nèi)容,傳遞到模板中的數(shù)據(jù)為query
  • 參數(shù)page表示當前頁碼
<html>
<head>
    <title>全文檢索--結(jié)果頁</title>
</head>
<body>
<h2>搜索?<b>{{query}}</b>?結(jié)果如下:</h2>
<ul>
{%for item in page%}
    <li>{{item.object.id}}--{{item.object.gcontent|safe}}</li>
{%empty%}
    <li>啥也沒找到</li>
{%endfor%}
</ul>
<hr>
{%for pindex in page.paginator.page_range%}
    {%if pindex == page.number%}
        {{pindex}}??
    {%else%}
        <a href="?q={{query}}&page={{pindex}}">{{pindex}}</a>??
    {%endif%}
{%endfor%}
</body>
</html>

No.6 發(fā)送郵件

Django中內(nèi)置了郵件發(fā)送功能,被定義在django.core.mail模塊中。發(fā)送郵件需要使用SMTP服務器,常用的免費服務器有:163、126、QQ,下面以163郵件為例

注冊163郵箱itcast88,登錄后設置->POP3/SMTP/IMAP->客戶端授權(quán)密碼->開啟->填寫授權(quán)碼->確定

打開mysite/settings.py文件,點擊下圖配置。

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
#發(fā)送郵件的郵箱
EMAIL_HOST_USER = 'dingzefeng2017@163.com'
#在郵箱中設置的客戶端授權(quán)密碼
EMAIL_HOST_PASSWORD = '******'
#收件人看到的發(fā)件人
EMAIL_FROM = 'python<dingzefeng2017@163.com>'

在app01/views.py文件中新建視圖send

from django.conf import settings
from django.core.mail import send_mail
from django.http import HttpResponse
...
def send(request):
    msg='<a  target="_blank">點擊激活</a>'
    send_mail('注冊激活','',settings.EMAIL_FROM,
              ['dingzefeng2017@163.com'],
              html_message=msg)
    return HttpResponse('ok')

在app01/urls.py文件中配置

url(r'^send/$',views.send),

No.7 celery

用戶發(fā)起request,并等待response返回,可能需要執(zhí)行一段耗時的程序,那么用戶就會等待很長時間,造成不好的用戶體驗,比如發(fā)送郵件、手機驗證碼等,使用celery后,情況就不一樣了。解決:將耗時的程序放到celery中執(zhí)行

  • 點擊查看celery官方網(wǎng)站
  • 點擊查看celery中文文檔

celery名詞:

  • 任務task:就是一個Python函數(shù)。
  • 隊列queue:將需要執(zhí)行的任務加入到隊列中。
  • 工人worker:在一個新進程中,負責執(zhí)行隊列中的任務。
  • 代理人broker:負責調(diào)度,在布置環(huán)境中使用redis。

安裝包:

celery==3.1.25
django-celery==3.1.17

栗子

在app01/views.py文件中創(chuàng)建視圖sayhello

import time
...
def sayhello(request):
    print('hello ...')
    time.sleep(2)
    print('world ...')
    return HttpResponse("hello world")

在app01/urls.py中配置

url(r'^sayhello$',views.sayhello),

在app01/settings.py中安裝

INSTALLED_APPS = (
  ...
  'djcelery',
}

在app01/settings.py文件中配置代理和任務模塊

import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://127.0.0.1:6379/2'

在app01/目錄下創(chuàng)建tasks.py文件

import time
from celery import task

@task
def sayhello():
    print('hello ...')
    time.sleep(2)
    print('world ...')

打開app01/views.py文件,修改sayhello視圖如下:

from app01 import tasks
...
def sayhello(request):
    # print('hello ...')
    # time.sleep(2)
    # print('world ...')
    tasks.sayhello.delay()
    return HttpResponse("hello world")

執(zhí)行遷移生成celery需要的數(shù)據(jù)表

啟動Redis,如果已經(jīng)啟動則不需要啟動

sudo service redis start

啟動worker

python manage.py celery worker --loglevel=info

打開app01/task.py文件,修改為發(fā)送郵件的代碼,就可以實現(xiàn)無阻塞發(fā)送郵件

from django.conf import settings
from django.core.mail import send_mail
from celery import task

@task
def sayhello():
    msg='<a  target="_blank">點擊激活</a>'
    send_mail('注冊激活','',settings.EMAIL_FROM,
              ['dingzefeng2017@163.com'],
              html_message=msg)

No.8 部署

當項目開發(fā)完成后,需要將項目代碼放到服務器上,這個服務器擁有固定的IP,再通過域名綁定,就可以供其它人瀏覽,對于python web開發(fā),可以使用wsgi、apache服務器,此處以wsgi為例進行布署。

服務器首先是物理上的一臺性能高、線路全、運行穩(wěn)定的機器,分為私有服務器、公有服務器。

  • 私有服務器:公司自己購買、自己維護,只布署自己的應用,可供公司內(nèi)部或外網(wǎng)訪問,成本高,需要專人維護,適合大公司使用。
  • 公有服務器:集成好運營環(huán)境,銷售空間或主機,供其布署自己的應用,適合初創(chuàng)公司使用,成本低。

常用的公有服務器,如阿里云、×××等,可按流量收費或按時間收費。服務器還需要安裝服務器軟件,此處需要uWSGI、Nginx。

服務器架構(gòu)如下圖:

Python全棧開發(fā)之Django進階

布署前需要關(guān)閉調(diào)試、允許任何機器訪問,打開app01/settings.py文件

DEBUG = False
ALLOW_HOSTS=['*',]

WSGI

在生產(chǎn)環(huán)境中使用WSGI作為python web的服務器。WSGI:全拼為Python Web Server Gateway Interface,Python Web服務器網(wǎng)關(guān)接口,是Python應用程序或框架和Web服務器之間的一種接口,被廣泛接受。WSGI沒有官方的實現(xiàn), 因為WSGI更像一個協(xié)議,只要遵照這些協(xié)議,WSGI應用(Application)都可以在任何服務器(Server)上運行。

項目默認會生成一個wsgi.py文件,確定了settings模塊、application對象。

  • application對象:在Python模塊中使用application對象與應用服務器交互。
  • settings模塊:用于進行項目配置。

uWSGI

uWSGI實現(xiàn)了WSGI的所有接口,是一個快速、自我修復、開發(fā)人員和系統(tǒng)管理員友好的服務器,uWSGI代碼完全用C編寫,效率高、性能穩(wěn)定

安裝uWSGI

pip install uwsgi

配置uWSGI,在項目目錄下創(chuàng)建uwsgi.ini文件,配置如下:

[uwsgi]
#使用nginx連接時使用
#socket=127.0.0.1:8080
#直接做web服務器使用
http=127.0.0.1:8080
#項目目錄
chdir=/home/python/Desktop/pytest/mysite
#項目中wsgi.py文件的目錄,相對于項目目錄
wsgi-file=app01/wsgi.py
processes=4
threads=2
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log

啟動

uwsgi --ini uwsgi.ini

查看

ps ajx|grep uwsgi

停止

uwsgi --stop uwsgi.pid

測試沒問題,將配置中啟用socket,禁用http

[uwsgi]
#使用nginx連接時使用
socket=127.0.0.1:8080
#直接做web服務器使用
#http=127.0.0.1:8080
#項目目錄
chdir=/home/python/Desktop/pytest/mysite
#項目中wsgi.py文件的目錄,相對于項目目錄
wsgi-file=app01/wsgi.py
processes=4
threads=2
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log

停止uwsgi服務,然后再啟動uwsgi

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI