Django進階篇

Django路由映射FBV 和 CBV

django中請求處理方式有2種:FBV(function base views) 和 CBV(class base views),換言之就是一種用函數處理請求,一種用類處理請求。javascript

FBVcss

# url.py
from django.conf.urls import url, include
from mytest import views
 
urlpatterns = [
    url(r‘^index/‘, views.index),
]

# views.py
from django.shortcuts import render
 
 
def index(req):
    if req.method == ‘POST‘:
        print(‘method is :‘ + req.method)
    elif req.method == ‘GET‘:
        print(‘method is :‘ + req.method)
    return render(req, ‘index.html‘)
View Code

CBVhtml

# urls.py
from mytest import views
 
urlpatterns = [
    # url(r‘^index/‘, views.index),
    url(r‘^index/‘, views.Index.as_view()),
]

# views.py
from django.views import View

 
class Index(View):
    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
 
    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

# 注:類要繼承 View ,類中函數名必須小寫。
View Code

關於CBV模式下的一個拓展java

# cbv 模式下繼承了django的view類
# 在請求來臨的時候,會調用繼承類的 dispatch 方法
# 經過反射的方法它會去調用本身寫的視圖函數, 那麼這即是一個切入點,能夠在本身的 cbv 視圖中,重寫這個方法。 
class View(object):

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        else:
            handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs)
View Code

分頁

1、Django內置分頁

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

L = []
for i in range(999):
    L.append(i)       # 模擬數據庫 生成數據

def index(request):
    current_page = request.GET.get('page')  # 經過get請求獲得當前請求的頁數

    paginator = Paginator(L, 10)            # 實例化傳入倆個參數(全部數據,當頁顯示條數)
    # per_page: 每頁顯示條目數量
    # count:    數據總個數
    # num_pages:總頁數
    # page_range:總頁數的索引範圍,如: (1,10),(1,200)
    # page:     page對象
    try:
        posts = paginator.page(current_page)# 傳入當前頁碼,觀源碼可得實例化了一個Page對象
        # has_next              是否有下一頁
        # next_page_number      下一頁頁碼
        # has_previous          是否有上一頁
        # previous_page_number  上一頁頁碼
        # object_list           分頁以後的數據列表
        # number                當前頁
        # paginator             paginator對象
    except PageNotAnInteger:    # 不是數字
        posts = paginator.page(1)
    except EmptyPage:           # 超出頁碼範圍
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})  # posts封裝了一些方法
Views.py
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
      <span class="step-links">
        {% if posts.has_previous %}
            <a href="?p={{ posts.previous_page_number }}">上一頁</a>
        {% endif %}
          <span class="current">
            Page {{ posts.number }} of {{ posts.paginator.num_pages }}.  
          </span>
          {% if posts.has_next %}
              <a href="?p={{ posts.next_page_number }}">下一頁</a>
          {% endif %}
      </span>

</div>
</body>
</html>
HTML

那麼、Django的內置分頁基本倆個類實現、並封裝了一些方法來使用、此時並不能知足有一些的需求python

2、Django內置分頁的拓展

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

user = []
for i in range(1, 1001):
    dic = {'name': 'root' + str(i), 'pwd': i}
    user.append(dic)


class DiyPaginator(Paginator):
    def __init__(self, current_page,max_pager_num, *args, **kwargs):
        """
        :param current_page:  當前頁碼
        :param max_pager_num: 顯示頁碼個數的最大值
        :param args:
        :param kwargs:
        """
        self.current_page = int(current_page)
        self.max_pager_num = int(max_pager_num)
        super(DiyPaginator,self).__init__(*args,**kwargs)

    def pager_num_range(self):
        # 須要的參數
        # 當前頁碼    self.current_page
        # 頁碼數量    self.max_pager_num
        # 總頁數      self.num_pages

        # 若是總頁數小於頁碼個數最大值的狀況
        if self.num_pages < self.max_pager_num:
            return range(1,self.num_pages+1)     # 返回 從 1 到 總頁數

        # 若是總頁數大於頁碼數量且當前所選頁碼小於頁碼數量的一半    
        part = self.max_pager_num//2
        if self.current_page <= part:
            return range(1,self.max_pager_num+1) # 返回 從 1 到 頁碼個數最大值

        # 若是當前頁碼加一半的頁碼 大於 總頁數
        if (self.current_page+part) > self.num_pages:
            # 返回 從總頁數-最大頁碼數 到 總頁數      range的用法在此不做解釋
            # 例如 96頁+5頁 超出總頁數 則返回的範圍是 從 總頁數-最大頁碼數量+1 到 總頁數+1    
            return range(self.num_pages-self.max_pager_num+1,self.num_pages+1)

        # 其他狀況從 當前頁碼減去顯示頁碼的平均值開始  到 當前頁碼加顯示頁碼的平均值(並加一)結束
        return range(self.current_page-part,self.current_page+part+1)


def index(request):
    p = request.GET.get('page')
    start = (int(p)-1)*10
    end = int(p)*10
    data = user[start:end]
    return render(request,'index.html',{'data':data,'user':user})


def index1(request):
    current_page = request.GET.get('page')
    paginator = DiyPaginator(current_page, 9, user, 10)
    # Paginator所封裝的方法
    # per_page: 每頁顯示條目數量
    # count:    數據總個數
    # num_pages:總頁數
    # page_range:總頁數的索引範圍,如: (1,10),(1,200)
    # page:     page對象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一頁
        # next_page_number      下一頁頁碼
        # has_previous          是否有上一頁
        # previous_page_number  上一頁頁碼
        # object_list           分頁以後的數據列表
        # number                當前頁
        # paginator             paginator對象
    except PageNotAnInteger:      # 不是整形數字
        posts = paginator.page(1)
    except EmptyPage:             # 若是是空值
        posts = paginator.page(paginator.num_pages)

    return render(request,'index1.html',{'posts':posts})
擴展內置分頁:views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        {% for row in posts.object_list %}
            <li>{{ row.name }}-{{ row.pwd }}</li>
        {% endfor %}
    </ul>
    {% include 'include/pager.html' %}
</body>
</html>

##################################
include 組件代碼

{% if posts.has_previous %}
    <a href="/index1?page={{ posts.previous_page_number }}">上一頁</a>
{% endif %}

{% for num in posts.paginator.pager_num_range %}
    {% if num == posts.number %}
        <a style="color: red;font-size: 20px" href="/index1?page={{ num }}">{{ num }}</a>
    {% else %}
        <a href="/index1?page={{ num }}">{{ num }}</a>
    {% endif %}
{% endfor %}

{% if posts.has_next %}
    <a href="/index1?page={{ posts.next_page_number }}">下一頁</a>
{% endif %}
<span>
    當前頁:{{ posts.number }}&nbsp;&nbsp;總頁數:{{ posts.paginator.num_pages }}
</span>
擴展內置分頁:HTML

3、自定義分頁(適用於任何地方)

  • 建立處理分頁數據的類
  • 根據分頁數據獲取數據
  • 輸出分頁HTML,即:[上一頁][1][2][3][4][5][下一頁]或者額外的做出一些拓展也能夠

建立處理分頁數據的類時,大體也須要四個參數(詳情觀看類構造方法)jquery

  一、爲了減小服務器內存的負載,再也不獲取全部數據的,而是得到全部數據的總個數,而後再根據索引查數據庫的內容數據庫

  二、當前頁碼django

  三、每頁顯示的行數json

  四、頁碼顯示的數量bootstrap

對於頁數的顯示大體也能夠歸類爲三種狀況(詳情觀看類中page_num_range函數)

  一、計算的總頁數小於頁碼顯示的數量

  二、計算的總頁數大於頁碼顯示的數量

    A、當前頁數小於頁碼數量的一半

    B、當前頁數加頁碼數量的一半超出總頁數的範圍

  三、正常狀況

    從 當前頁數 減 一半頁碼數量 到 當前頁數 加 一半頁碼數量

class Pagination(object):
    def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=9):
        """
        :param totalCount:     全部數據總個數
        :param currentPage:    當前頁數
        :param perPageItemNum: 每頁顯示行數
        :param maxPageNum:     最多顯示頁碼個數
        """
        self.total_count = totalCount
        # 對當前的頁碼進行一次異常捕獲
        try:
            currentPage = int(currentPage)
            if currentPage <= 0:
                currentPage = 1
            self.current_page = currentPage
        except Exception:
            self.current_page = 1
        self.per_page_item_num = perPageItemNum
        self.max_page_num = maxPageNum

    @property
    def start(self):
        # 數據索引開始的值
        return (self.current_page-1) * self.per_page_item_num

    @property
    def end(self):
        # 數據索引結束的值
        return self.current_page * self.per_page_item_num

    @property
    def num_pages(self):
        """
        總頁數
        :return:
        """
        # 得商取餘得內置函數
        x, o = divmod(self.total_count,self.per_page_item_num)
        if o == 0:
            return x
        return x + 1

    @property
    def page_num_range(self):
        if self.num_pages < self.max_page_num:
            return range(1, self.num_pages+1)

        part = self.max_page_num//2
        if self.current_page <= part:
            return range(1,self.max_page_num+1)

        if (self.current_page+part) > self.num_pages:
            return range(self.num_pages-self.max_page_num+1, self.num_pages+1)
        return range(self.current_page-part, self.current_page+part+1)

    def page_str(self):
        page_list = []

        first = "<li><a href='/index2/?page=1'>首頁</a></li>"
        page_list.append(first)

        if self.current_page == 1:
            prev_page = "<li><a href='#'>上一頁</a></li>"
        else:
            prev_page = "<li><a href='/index2/?page=%s'>上一頁</a></li>" %(self.current_page-1)
        page_list.append(prev_page)

        for i in self.page_num_range:
            if i == self.current_page:
                temp = "<li class='active'><a href='/index2/?page=%s'>%s</a></li>" %(i,i)
            else:
                temp = "<li><a href='/index2/?page=%s'>%s</a></li>" % (i, i)
            page_list.append(temp)

        if self.current_page == self.num_pages:
            next_page = "<li><a href='#'>下一頁</a></li>"
        else:
            next_page = "<li><a href='/index2/?page=%s'>下一頁</a></li>" %(self.current_page+1)
        page_list.append(next_page)

        last = "<li><a href='/index2/?page=%s'>尾頁</a></li>" %self.num_pages
        page_list.append(last)

        return ''.join(page_list)
自定義分頁
def index2(request):
    from page.diypage import Pagination
    current_page = request.GET.get('page')
    page_obj = Pagination(1000,current_page)

    data_list = user[page_obj.start:page_obj.end]
    return render(request,'index2.html',{
        'data' : data_list,
        'page_obj' : page_obj
    })
自定義分頁:views.py
# 本頁面引用了bootstrap樣式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css" />
</head>
<body>
    <ul>
        {% for row in data %}
            <li>{{ row.name }}-{{ row.pwd }}</li>
        {% endfor %}
    </ul>
    {% for i in page_obj.pager_num_range %}
        <a href="/index2/?page={{ i }}">{{ i }}</a>
    {% endfor %}
    <hr/>

    <ul class="pagination pagination-sm">
        {{ page_obj.page_str|safe }}
      </ul>
    <div style="height: 300px;"></div>
</body>
</html>
自定義分頁:HTML

序列化

  序列化是將對象狀態轉換爲可保持或傳輸的格式的過程

  反序列化是指將存儲在存儲媒體中的對象狀態裝換成對象的過程 

  例如遊戲都有存檔的功能、再次開始的時候只需讀檔便可(這便是一個序列化與反序列的過程)

  序列化也能夠將一個對象傳遞到另外一個地方的

  關於Django中的序列化主要應用在將數據庫中檢索的數據返回給客戶端用戶,特別的Ajax請求通常返回的爲Json格式。

一、serializers

from django.core import serializers
 
ret = models.BookType.objects.all()
 
data = serializers.serialize("json", ret)

二、json.dumps

複製代碼
import json
 
#ret = models.BookType.objects.all().values('caption')
ret = models.BookType.objects.all().values_list('caption')
 
ret=list(ret)
 
result = json.dumps(ret)
複製代碼

三、from django.http import JsonResponse

django JsonResponse不支持返回列表形式的序列化。例如看看這個類的構造方法是怎麼樣執行的...

class JsonResponse(HttpResponse):
    """
    將數據序列化成爲JSON的Http響應類

    :param data: Data to be dumped into json. By default only ``dict`` objects
      are allowed to be passed due to a security flaw before EcmaScript 5. See
      the ``safe`` parameter for more information.
    :param encoder: Should be an json encoder class. Defaults to
      ``django.core.serializers.json.DjangoJSONEncoder``.
    :param safe: Controls if only ``dict`` objects may be serialized. Defaults
      to ``True``.
    :param json_dumps_params: A dictionary of kwargs passed to json.dumps().
    """

    def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        # 若是safe爲True 和 data 不是 dict的實例對象 則拋出異常
        if safe and not isinstance(data, dict):
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super(JsonResponse, self).__init__(content=data, **kwargs)
View Code

Cookices

Cookie是存儲在用戶瀏覽器上的一個鍵值對

A、獲取Cookies

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    參數:
        default: 默認值
           salt: 加密鹽
        max_age: 後臺控制過時時間

B、設置Cookies

複製代碼
rep = HttpResponse(...) 或 rep = render(request, ...)
 
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密鹽',...)
    參數:
        key,              鍵
        value='',         值
        max_age=None,     超時時間
        expires=None,     超時時間(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路徑,/ 表示根路徑,特殊的:跟路徑的cookie能夠被任何url的頁面訪問
        domain=None,      Cookie生效的域名
        secure=False,     https傳輸
        httponly=False    只能http協議傳輸,沒法被JavaScript獲取(不是絕對,底層抓包能夠獲取到也能夠被覆蓋)
複製代碼

C、因爲Cookies保存在客戶端的電腦上,因此,JavaScript和jquery也能夠操做cookie.

     更多詳情更新中...

Session

Session是存儲在服務器的一組鍵值對,且它依賴於Cookie,且安全係數比Cookie高

Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:

  • 數據庫(默認)
  • 緩存
  • 文件
  • 緩存+數據庫
  • 加密cookie

A、數據庫Session

Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路徑(默認)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默認)
    SESSION_COOKIE_SECURE = False                            # 是否Https傳輸cookie(默認)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http傳輸(默認)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默認)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否關閉瀏覽器使得Session過時(默認)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次請求都保存Session,默認修改以後才保存(默認)
 
 
 
b. 使用
 
    def index(request):
        # 獲取、設置、刪除Session中數據
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在則不設置
        del request.session['k1']
 
        # 全部 鍵、值、鍵值對
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用戶session的隨機字符串
        request.session.session_key
 
        # 將全部Session失效日期小於當前日期的數據刪除
        request.session.clear_expired()
 
        # 檢查 用戶session的隨機字符串 在數據庫中是否
        request.session.exists("session_key")
 
        # 刪除當前用戶的全部Session數據
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 若是value是個整數,session會在些秒數後失效。
            * 若是value是個datatime或timedelta,session就會在這個時間後失效。
            * 若是value是0,用戶關閉瀏覽器session就會失效。
            * 若是value是None,session會依賴全局session失效策略。
數據庫Session

跨站請求僞造

Django爲用戶實現防止跨站請求僞造的功能,經過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求僞造功能有分爲全局和局部。

全局:

  中間件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,爲當前函數強制設置防跨站請求僞造功能,即使settings中沒有設置全局中間件。
  • @csrf_exempt,取消當前函數防跨站請求僞造功能,即使settings中設置了全局中間件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

 

Django中間件 

django 中的中間件(middleware),在django中,中間件其實就是一個類,在請求到來和結束後,django會根據本身的規則在合適的時機執行中間件中相應的方法。 

在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每個元素就是一箇中間件,以下圖。

 例如,能夠在項目中的任何地方建立一個middleware.py的文件(可隨意建立, 註冊中間件的時候配置好路徑便可)

中間件中能夠定義四個方法,分別是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值能夠是None和HttpResonse對象,若是是None,則繼續按照django定義的規則向下執行,若是是HttpResonse對象,則直接將該對象返回給用戶。

自定義中間件

一、建立中間件 

複製代碼
class CustomMiddleware(object):
      
    def process_request(self,request):
        pass

    def process_view(self, request, callback, callback_args, callback_kwargs):
        i =1

    def process_exception(self, request, exception):
        pass
      
    def process_response(self, request, response):
        return response
複製代碼

二、註冊中間件

如第一圖所示最後一條,可根據自身業務去自定義一些中間件操做。  

Django信號

1,django內置信號

複製代碼
Model signals
    pre_init                    # django的modal執行其構造方法前,自動觸發
    post_init                   # django的modal執行其構造方法後,自動觸發
    pre_save                    # django的modal對象保存前,自動觸發
    post_save                   # django的modal對象保存後,自動觸發
    pre_delete                  # django的modal對象刪除前,自動觸發
    post_delete                 # django的modal對象刪除後,自動觸發
    m2m_changed                 # django的modal中使用m2m字段操做第三張表(add,remove,clear)先後,自動觸發
    class_prepared              # 程序啓動時,檢測已註冊的app中modal類,對於每個類,自動觸發
Management signals
    pre_migrate                 # 執行migrate命令前,自動觸發
    post_migrate                # 執行migrate命令後,自動觸發
Request/response signals
    request_started             # 請求到來前,自動觸發
    request_finished            # 請求結束後,自動觸發
    got_request_exception       # 請求異常後,自動觸發
Test signals
    setting_changed             # 使用test測試修改配置文件時,自動觸發
    template_rendered           # 使用test測試渲染模板時,自動觸發
Database Wrappers
    connection_created          # 建立數據庫鏈接時,自動觸發
複製代碼

調用內置信號的倆種形式

 

2,django自定義信號

1 )、定義信號

全部的信號都是 `django.dispatch.Signal` 的實例、那麼在項目某個app下建立 名爲 `custom_signals.py` 的文件,以下這麼寫

複製代碼
# filename: custom_singals.py

import django.dispatch

# 聲明瞭一個 `pizza_done` 信號,它將爲接收者提供 `toppings`, `size` 參數
# 能夠在任什麼時候候更改這個參數列表
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
複製代碼

並配置信號回調函數

在項目某個app下建立 名爲 `register.py` 的文件,以下這麼寫

複製代碼
# filename: register.py
# 註冊信號使用

from app01.custom_singals import pizza_done


def pizza_done_func(sender, **kwargs):
    print("msg:", sender, kwargs)


pizza_done.connect(pizza_done_func)
複製代碼

2 )、註冊信號

項目啓動的時候要將這些信號註冊,那麼在對應 `app` 的 `apps.py` 文件中以下

複製代碼
# filename: app_name/apps.py

from django.apps import AppConfig

# `django` 工具包中封裝好的動態導入模塊的方法
from django.utils.module_loading import import_module  


class App01Config(AppConfig):
    name = 'app01'

    def ready(self):
        # 項目啓動全部 `app` 的 `ready` 方法下的代碼均會執行
        import_module("app01.register")  # 註冊信號
複製代碼

3 )、發送信號

事先定義 一組 `url` 映射關係,在視圖業務操做中發送咱們的信號( 有倆種發送信號的方法 )

複製代碼
from django.shortcuts import HttpResponse

from app01.custom_singals import pizza_done


# Create your views here.

class PizzaStore:

    def send_pizza(self, toppings, size):
        # 發送信號
        pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
        # "OR"   上下倆個方法是等價的, 區別 ~ ~
        pizza_done.send_robust(sender=self.__class__, toppings=toppings, size=size)


def index(request, ):
    # 業務操做, 執行信號發送操做
    PizzaStore().send_pizza("chicken", "40")
    return HttpResponse("ok")
複製代碼

Django自定義manage.py命令

正如以前,已經所知一些 `Django` 的一些命令, 例如 runserver、migrate....,那麼它們執行的機制是如何的呢,是否能夠作一些其它的命令知足咱們的一些需求呢,請看下文

在 APP 建立相關目錄路徑,`closepoll.py` 即是自定義的命令文件

複製代碼
polls/
    __init__.py
    models.py
    management/
        __init__.py
        commands/
            __init__.py
            closepoll.py
    tests.py
    views.py
複製代碼

文件裏面必須繼承基類,並實現抽象方法 `handle`

複製代碼
from django.core.management.base import BaseCommand, CommandError
from polls.models import Question as Poll

class Command(BaseCommand):
    help = 'Closes the specified poll for voting'

    def add_arguments(self, parser):
     # 添加自定義參數,例如 python manage.py runserver -h 0.0.0.0 -p 8080  這樣子 ~~
        parser.add_argument('poll_id', nargs='+', type=int) 

    def handle(self, *args, **options):
        for poll_id in options['poll_id']:
            try:
                poll = Poll.objects.get(pk=poll_id)
            except Poll.DoesNotExist:
                raise CommandError('Poll "%s" does not exist' % poll_id)

            poll.opened = False
            poll.save()

            self.stdout.write(self.style.SUCCESS('Successfully closed poll "%s"' % poll_id))
複製代碼

運行自定義命令

python3 manage.py closepoll -poll_id 10

# 上述是在命令行運行文件,那麼在代碼中如何運行,
from django.core import management
management.call_command('closepoll', args=()) # 參數詳解待更新
相關文章
相關標籤/搜索