Django4.0 基于類的視圖-在基于類的視圖中使用混入

2022-03-16 17:58 更新

Django 內(nèi)置的基于類的視圖提供了很多功能,但你可能想單獨(dú)使用有些功能。例如,你可能想寫一個(gè)渲染一個(gè)模板來生成 HTTP 響應(yīng)的視圖,但你不能使用 ?TemplateView ?;也許你只需要在 POST 時(shí)渲染一個(gè)模板,用 GET 來處理其他所有事。雖然你可以直接使用 ?TemplateResponse?,但這很可能會(huì)導(dǎo)致重復(fù)代碼。

因此 Django 也提供了很多混入,它們提供了更多的離散功能。比如模板渲染,被封裝在 ?TemplateResponseMixin ?中。

上下文和模板響應(yīng)

提供了兩個(gè)重要的混入,它們有助于在基于類的視圖中使用模板時(shí)提供一個(gè)一致的接口。

TemplateResponseMixin

每個(gè)返回 ?TemplateResponse的內(nèi)置視圖都將調(diào)用 ?TemplateResponseMixin提供的 ?render_to_response() 方法。大多數(shù)時(shí)候,這個(gè)方法會(huì)被你調(diào)用(例如,它被 ?TemplateView?和 ?DetailView?共同實(shí)現(xiàn)的 ?get()方法調(diào)用);同樣,你也不太可能需要覆蓋它,但如果你想讓你的響應(yīng)返回一些沒有通過 Django 模板渲染的東西,那么你會(huì)想要這樣做。

render_to_response()本身會(huì)調(diào)用 ?
get_template_names()? ,默認(rèn)情況下,它會(huì)在基于類的視圖上查找 ?
template_name;另外兩個(gè)混入( ?SingleObjectTemplateResponseMixin?和 ?MultipleObjectTemplateResponseMixin)覆蓋了這一點(diǎn),以在處理實(shí)際對(duì)象時(shí)提供更靈活的默認(rèn)值。

ContextMixin

每個(gè)需要上下文數(shù)據(jù)的內(nèi)置視圖,比如為了渲染一個(gè)模板(包括上面的 ?TemplateResponseMixin?),都應(yīng)該將他們想確定傳入的數(shù)據(jù)作為關(guān)鍵字參數(shù)傳入 ?get_context_data()

調(diào)用。?get_context_data()返回一個(gè)字典;在 ?ContextMixin?中它返回它的關(guān)鍵字參數(shù),但通常覆蓋此項(xiàng)來增加更多成員到字典中。你也可以使用 ?extra_context屬性。

構(gòu)造 Django 基于類的通用視圖

讓我們看看 Django 的兩個(gè)基于類的通用視圖是如何由提供離散功能的混入構(gòu)建的。我們將考慮 ?DetailView ?,它渲染一個(gè)對(duì)象的 “詳情” 視圖,以及 ?ListView ?,它渲染一個(gè)對(duì)象列表,通常來自一個(gè)查詢集,并可選擇將它們分頁。這里將介紹四個(gè)混入,無論是在處理單個(gè) Django 對(duì)象還是多個(gè)對(duì)象時(shí),它們都提供了有用的功能。
通用編輯視圖( ?FormView?,和模型專用的視圖 ?CreateView?,?UpdateView ?和 ?DeleteView ?),以及基于日期的通用視圖中也涉及到混入

DetailView :使用單個(gè) Django 對(duì)象

要顯示一個(gè)對(duì)象的詳情,我們基本上需要做兩件事:我們需要查詢對(duì)象,然后將該對(duì)象作為上下文,用一個(gè)合適的模板生成一個(gè) ?TemplateResponse ?。
為了得到對(duì)象,?DetailView ?依賴于 ?SingleObjectMixin ?,它提供一個(gè) ?get_object()? 方法,該方法根據(jù)請(qǐng)求的 URL 來找出對(duì)象(它查找 ?URLconf ?中聲明的 ?pk ?和 ?slug ?關(guān)鍵字參數(shù),并從視圖上的 ?model ?屬性查找對(duì)象,或者從提供的 ?queryset ?屬性中查找)。?SingleObjectMixin ?還覆蓋了 ?get_context_data()? ,它被用于所有 Django 內(nèi)置的基于類的視圖,為模板渲染提供上下文數(shù)據(jù)。
然后為了生成一個(gè) ?TemplateResponse?, ?DetailView ?使用了 ?SingleObjectTemplateResponseMixin?,它擴(kuò)展了 ?TemplateResponseMixin?,如上所述的覆蓋了 ?get_template_names()?。它實(shí)際上提供了一組相當(dāng)復(fù)雜的選項(xiàng),但大多數(shù)人都會(huì)使用的主要選項(xiàng)是 ?<app_label>/<model_name> _detail.html?。?_detail? 部分可以通過在子類上設(shè)置 ?template_name_suffix ?來改變。(例如 通用編輯視圖 的創(chuàng)建和更新視圖使用 ?_form?,刪除視圖使用 ?_confirm_delete?。)

ListView :使用多個(gè) Django 對(duì)象

對(duì)象列表大致遵循相同的模式:我們需要一個(gè)(可能是分頁的)對(duì)象列表,通常是 ?QuerySet ?,然后根據(jù)這個(gè)對(duì)象列表使用合適的模板生成 ?TemplateResponse ?。
為了得到對(duì)象,?ListView ?使用了 ?MultipleObjectMixin ?,它同時(shí)提供 ?get_queryset()? 和 ?paginate_queryset()? 。與 ?SingleObjectMixin ?不同的是,不需要使用部分 URL 來找出要使用的查詢集,所以默認(rèn)使用視圖類上的 ?queryset ?或 ?model ?屬性。在這里覆蓋 ?get_queryset()? 的常見原因是為了動(dòng)態(tài)變化的對(duì)象,比如根據(jù)當(dāng)前用戶的情況,或者為了排除博客未來的文章。
?MultipleObjectMixin ?還覆蓋了 ?get_context_data()?,為分頁加入了適當(dāng)?shù)纳舷挛淖兞浚ㄈ绻猪摫唤?,則提供虛假分頁)。它依賴于 ?ListView ?作為關(guān)鍵字參數(shù)傳入的 ?object_list?。
要生成一個(gè) ?TemplateResponse ?,?ListView ?則使用 ?MultipleObjectTemplateResponseMixin ?;和上面的 ?SingleObjectTemplateResponseMixin ?一樣,它覆蓋 ?get_template_names()? 來提供一系列選項(xiàng),最常用的 ?<app_label>/<model_name>_list.html ?,?_list? 部分同樣從 ?template_name_suffix ?屬性中獲取。(基于日期的通用視圖使用諸如 ?_archive? 、?_archive_year? 等后綴來為各種專門的基于日期的列表視圖使用不同的模板。)

使用 Django 的基于類的視圖混入

現(xiàn)在我們已經(jīng)知道 Django 的基于類的通用視圖如何使用所提供的混入,讓我們看看使用它們的其他方式。我們?nèi)匀粫?huì)將它們與內(nèi)置的基于類的視圖,或者其他通用的基于類的視圖結(jié)合起來,但是,有一系列比 Django 開箱即用所提供的更罕見的問題可以被解決。

注意:不是所有的混入都可以一起使用,并且不是所有的基于類的通用視圖能和所有其他的混入一起使用。這里我們介紹一些有用的例子;如果你想把其他功能匯集在一起,那么你就必須考慮你正在使用的不同類之間重疊的屬性和方法之間的相互作用,以及 ?method resolution order? 將如何影響哪些版本的方法將以何種順序被調(diào)用。

如果有問題,最好還是退而求其次,以 ?View ?或 ?TemplateView ?為基礎(chǔ),或許可以用 ?SingleObjectMixin? 和 ?MultipleObjectMixin ?。雖然你最終可能會(huì)寫出更多的代碼,但對(duì)于以后再來的人來說,更有可能清楚地理解,并且由于需要擔(dān)心的交互較少,你可以省去一些思考。

在視圖中使用 SingleObjectMixin

如果我們想編寫一個(gè)只響應(yīng) POST 的基于類的視圖,我們將子類化 View 并且在子類中編寫一個(gè) post() 方法。但是如果想讓我們的程序在一個(gè)從 URL 中識(shí)別出來特定的對(duì)象上工作,我們就需要 ?SingleObjectMixin ?提供的功能。

我們將使用我們?cè)诨陬惖耐ㄓ靡晥D介紹中使用的 Author 模型來演示這一點(diǎn)。

from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.urls import reverse
from django.views import View
from django.views.generic.detail import SingleObjectMixin
from books.models import Author

class RecordInterestView(SingleObjectMixin, View):
    """Records the current user's interest in an author."""
    model = Author

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()

        # Look up the author we're interested in.
        self.object = self.get_object()
        # Actually record interest somehow here!

        return HttpResponseRedirect(reverse('author-detail', kwargs={'pk': self.object.pk}))

在實(shí)際操作中,你可能會(huì)希望把興趣記錄在一個(gè)鍵值存儲(chǔ)中,而不是關(guān)系數(shù)據(jù)庫中,所以我們把關(guān)于數(shù)據(jù)庫的省略了。視圖在使用 ?SingleObjectMixin ?時(shí),我們唯一需要擔(dān)心的地方是想要查找我們感興趣的作者,它通過調(diào)用? self.get_object() ?來實(shí)現(xiàn)。其他的一切都由混入替我們處理。

我們可以很簡單的將它掛接在我們的 URLs 中:

from django.urls import path
from books.views import RecordInterestView

urlpatterns = [
    #...
    path('author/<int:pk>/interest/', RecordInterestView.as_view(), name='author-interest'),
]

注意 ?pk ?命名的組,?get_object()? 用它來查找 ?Author ?實(shí)例。你也可以使用 ?slug?,或者 ?SingleObjectMixin ?的任何其他功能。

在 ListView 中使用 SingleObjectMixin

?ListView ?提供了內(nèi)置的分頁功能,但你可能想將一個(gè)對(duì)象列表分頁,而這些對(duì)象都是通過一個(gè)外鍵鏈接到另一個(gè)對(duì)象的。在我們的出版示例中,你可能想對(duì)某一出版商的所有書籍進(jìn)行分頁。
一種方法是將 ?ListView ?和 ?SingleObjectMixin ?結(jié)合起來,這樣一來,用于圖書分頁列表的查詢集就可以脫離作為單個(gè)對(duì)象找到的出版商對(duì)象。 為此,我們需要兩個(gè)不同的查詢集:
?ListView ?使用的 Book 查詢集

由于我們已經(jīng)得到了我們所想要書籍列表的 Publisher ,我們只需覆蓋 ?get_queryset()? 并使用的 ?Publisher ?的 反向外鍵管理器。

?get_object()? 使用的 ?Publisher ?查詢集

我們將依賴 ?get_object()? 的默認(rèn)實(shí)現(xiàn)來獲取正確的 ?Publisher ?對(duì)象。然而,我們需要顯式地傳遞一個(gè) ?queryset ?參數(shù),因?yàn)??get_object() ?的默認(rèn)實(shí)現(xiàn)會(huì)調(diào)用 ?get_queryset()? ,我們已經(jīng)覆蓋了它并返回了 Book 對(duì)象而不是 Publisher 對(duì)象。

注解:我們必須認(rèn)真考慮 ?get_context_data()?。由于 ?SingleObjectMixin ?和 ?ListView ?會(huì)將上下文數(shù)據(jù)放在 ?context_object_name? 的值下(如果它已設(shè)置),我們要明確確保 ?Publisher ?在上下文數(shù)據(jù)中。?ListView ?將為我們添加合適的 ?page_obj ?和 ?paginator?,只要我們記得調(diào)用 ?super()?。

現(xiàn)在我們可以編寫一個(gè)新的 ?PublisherDetailView?:

from django.views.generic import ListView
from django.views.generic.detail import SingleObjectMixin
from books.models import Publisher

class PublisherDetailView(SingleObjectMixin, ListView):
    paginate_by = 2
    template_name = "books/publisher_detail.html"

    def get(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Publisher.objects.all())
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['publisher'] = self.object
        return context

    def get_queryset(self):
        return self.object.book_set.all()

注意看我們?nèi)绾卧??get()? 中設(shè)置 ?self.object? ,這樣我們可以在后面的 ?get_context_data()? 和 ?get_queryset()? 中再次使用它。如果你沒有設(shè)置 ?template_name ?,模板將為正常 ?ListView ?的默認(rèn)選項(xiàng),在這個(gè)例子里是 "?books/book_list.html?" ,因?yàn)樗菚牧斜恚?ListView ?對(duì) ?SingleObjectMixin ?一無所知,因此這個(gè)視圖和 ?Publisher ?沒有任何關(guān)系。
在這個(gè)例子中,?paginate_by ?被刻意地縮小了,所以你不需要?jiǎng)?chuàng)建很多書就能看到分頁的效果。這里是你要使用的模板:

{% extends "base.html" %}

{% block content %}
    <h2>Publisher {{ publisher.name }}</h2>

    <ol>
      {% for book in page_obj %}
        <li>{{ book.title }}</li>
      {% endfor %}
    </ol>

    <div class="pagination">
        <span class="step-links">
            {% if page_obj.has_previous %}
                <a href="?page={{ page_obj.previous_page_number }}">previous</a>
            {% endif %}

            <span class="current">
                Page {{ page_obj.number }} of {{ paginator.num_pages }}.
            </span>

            {% if page_obj.has_next %}
                <a href="?page={{ page_obj.next_page_number }}">next</a>
            {% endif %}
        </span>
    </div>
{% endblock %}

避免過度復(fù)雜的事情

一般來說,你可以在需要的時(shí)候使用 ?TemplateResponseMixin ?和 ?SingleObjectMixin ?的功能。如上所示,只要稍加注意,你甚至可以將 ?SingleObjectMixin ?和 ?ListView ?結(jié)合起來。然而當(dāng)你嘗試這樣做時(shí),事情會(huì)變得越來越復(fù)雜,一個(gè)好的經(jīng)驗(yàn)法則是:

提示:你的每個(gè)視圖應(yīng)該只使用混入或者來自一個(gè)通用基于類的視圖的組里視圖: 詳情,列表,編輯 和日期。例如,將 ?TemplateView ?(內(nèi)置視圖)和 ?MultipleObjectMixin ?(通用列表)結(jié)合起來,但你可能會(huì)在 ?SingleObjectMixin ?(通用詳情)和 ?MultipleObjectMixin ?(通用列表)結(jié)合時(shí)遇到問題。

為了說明當(dāng)您嘗試變得更復(fù)雜時(shí)會(huì)發(fā)生什么,我們展示了一個(gè)示例,該示例在有更簡單的解決方案時(shí)會(huì)犧牲可讀性和可維護(hù)性。 首先,讓我們看一個(gè)將 ?DetailView ?與 ?FormMixin ?結(jié)合起來的天真的嘗試,使我們能夠?qū)?nbsp;Django 表單發(fā)布到與使用 ?DetailView ?顯示對(duì)象相同的 URL。

DetailView 和 FormMixin 一起使用

回想一下我們之前使用 ?View ?和 ?SingleObjectMixin ?一起使用的例子。我們當(dāng)時(shí)記錄的是一個(gè)用戶對(duì)某個(gè)作者的興趣;比如說現(xiàn)在我們想讓他們留言說為什么喜歡他們。同樣,我們假設(shè)我們不打算把這個(gè)存儲(chǔ)在關(guān)系型數(shù)據(jù)庫中,而是存儲(chǔ)在更深?yuàn)W的東西中,我們?cè)谶@里就不關(guān)心了。
這時(shí)自然而然就會(huì)用到一個(gè) ?Form ?來封裝從用戶瀏覽器發(fā)送到 Django 的信息。又比如說我們?cè)??REST ?上投入了大量的精力,所以我們希望用同樣的 URL 來顯示作者和捕捉用戶的信息。讓我們重寫我們的 ?AuthorDetailView ?來實(shí)現(xiàn)這個(gè)目標(biāo)。
我們將保留 ?DetailView ?中的 ?GET ?處理,盡管我們必須在上下文數(shù)據(jù)中添加一個(gè) ?Form?,這樣我們就可以在模板中渲染它。我們還要從 ?FormMixin ?中調(diào)入表單處理,并寫一點(diǎn)代碼,這樣在 ?POST?時(shí),表單會(huì)被適當(dāng)?shù)卣{(diào)用。

注解:我們使用 ?FormMixin ?并自己實(shí)現(xiàn) ?post()?,而不是嘗試將 ?DetailView ?與 ?FormView ?混合(它已經(jīng)提供了合適的 ?post()?),因?yàn)閮蓚€(gè)視圖都實(shí)現(xiàn)了 ?get()?,事情會(huì)變得更加混亂。

我們新的 ?AuthorDetailView ?如下所示:

# CAUTION: you almost certainly do not want to do this.
# It is provided as part of a discussion of problems you can
# run into when combining different generic class-based view
# functionality that is not designed to be used together.

from django import forms
from django.http import HttpResponseForbidden
from django.urls import reverse
from django.views.generic import DetailView
from django.views.generic.edit import FormMixin
from books.models import Author

class AuthorInterestForm(forms.Form):
    message = forms.CharField()

class AuthorDetailView(FormMixin, DetailView):
    model = Author
    form_class = AuthorInterestForm

    def get_success_url(self):
        return reverse('author-detail', kwargs={'pk': self.object.pk})

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        # Here, we would record the user's interest using the message
        # passed in form.cleaned_data['message']
        return super().form_valid(form)

?get_success_url()? 提供了重定向的去處,它在 ?form_valid()? 的默認(rèn)實(shí)現(xiàn)中使用。如前所述,我們需要提供自己的 ?post()? 。

更好的解決方案

?FormMixin ?和 ?DetailView ?之間微妙交互已經(jīng)在測(cè)試我們管理事務(wù)的能力了。你不太可能想寫這樣的類。
在這個(gè)例子里,你可以編寫 ?post()? 讓 ?DetailView ?作為唯一的通用功能,盡管編寫 ?Form ?的處理代碼會(huì)涉及到很多重復(fù)的地方。
或者,使用單獨(dú)的視圖來處理表單仍然比上述方法工作量小,它可以使用 ?FormView ?,而不必?fù)?dān)心任何問題。

另一種更好的解決方案

我們?cè)谶@里真正想做的是使用來自同一個(gè) URL 的兩個(gè)不同的基于類的視圖。 那么為什么不這樣做呢? 我們這里有一個(gè)非常明確的劃分:?GET ?請(qǐng)求應(yīng)該獲取 ?DetailView?(將 ?Form ?添加到上下文數(shù)據(jù)中),?POST ?請(qǐng)求應(yīng)該獲取 ?FormView?。 讓我們先設(shè)置這些視圖。

?AuthorDetailView ?視圖與我們第一次介紹 ?AuthorDetailView ?時(shí)幾乎相同; 我們必須編寫自己的 ?get_context_data()? 以使 ?AuthorInterestForm ?可用于模板。 為了清楚起見,我們將跳過之前的 ?get_object()? 覆蓋:

from django import forms
from django.views.generic import DetailView
from books.models import Author

class AuthorInterestForm(forms.Form):
    message = forms.CharField()

class AuthorDetailView(DetailView):
    model = Author

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = AuthorInterestForm()
        return context

那么?AuthorInterestForm?是一個(gè)?FormView?,但是我們必須引入?SingleObjectMixin?,這樣我們才能找到我們正在談?wù)摰淖髡?,并且我們必須記住設(shè)置?template_name?以確保表單錯(cuò)誤會(huì)呈現(xiàn)與?AuthorDetailView?在GET上使用的模板相同的模板 :

from django.http import HttpResponseForbidden
from django.urls import reverse
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin

class AuthorInterestFormView(SingleObjectMixin, FormView):
    template_name = 'books/author_detail.html'
    form_class = AuthorInterestForm
    model = Author

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()
        self.object = self.get_object()
        return super().post(request, *args, **kwargs)

    def get_success_url(self):
        return reverse('author-detail', kwargs={'pk': self.object.pk})

最后,我們將它們放在一個(gè)新的 ?AuthorView ?視圖中。 我們已經(jīng)知道,在基于類的視圖上調(diào)用 ?as_view()? 會(huì)給我們一些行為與基于函數(shù)的視圖完全相同的東西,因此我們可以在兩個(gè)子視圖之間進(jìn)行選擇時(shí)這樣做。

您可以像在 ?URLconf ?中一樣將關(guān)鍵字參數(shù)傳遞給 ?as_view()?,例如,如果您希望 ?AuthorInterestFormView? 行為也出現(xiàn)在另一個(gè) URL 上,但使用不同的模板:

from django.views import View

class AuthorView(View):

    def get(self, request, *args, **kwargs):
        view = AuthorDetailView.as_view()
        return view(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        view = AuthorInterestFormView.as_view()
        return view(request, *args, **kwargs)

這個(gè)方式也可以被任何其他通用基于類的視圖,或你自己實(shí)現(xiàn)的直接繼承自 ?View ?或 ?TemplateView ?的基于類的視圖使用,因?yàn)樗共煌晥D盡可能分離。

不僅僅是HTML

基于類的視圖的優(yōu)勢(shì)是你可以多次執(zhí)行相同操作。假設(shè)你正在編寫 API,那么每個(gè)視圖應(yīng)該返回 JSON,而不是渲染 HTML。

我們可以創(chuàng)建一個(gè)混入類來在所有視圖里使用,用它來進(jìn)行一次轉(zhuǎn)換到 JSON。

比如,一個(gè) JSON 混入可以是這樣:

from django.http import JsonResponse

class JSONResponseMixin:
    """
    A mixin that can be used to render a JSON response.
    """
    def render_to_json_response(self, context, **response_kwargs):
        """
        Returns a JSON response, transforming 'context' to make the payload.
        """
        return JsonResponse(
            self.get_data(context),
            **response_kwargs
        )

    def get_data(self, context):
        """
        Returns an object that will be serialized as JSON by json.dumps().
        """
        # Note: This is *EXTREMELY* naive; in reality, you'll need
        # to do much more complex handling to ensure that arbitrary
        # objects -- such as Django model instances or querysets
        # -- can be serialized as JSON.
        return context

混入提供了 ?render_to_json_response()? 方法,其簽名與 ?render_to_response() ?相同。為了使用它,我們需要把它混入一個(gè) ?TemplateView ?里,并且重寫 ?render_to_response()? 來調(diào)用 ?render_to_json_response()? :

from django.views.generic import TemplateView

class JSONView(JSONResponseMixin, TemplateView):
    def render_to_response(self, context, **response_kwargs):
        return self.render_to_json_response(context, **response_kwargs)

同樣,我們可以將我們的 ?mixin ?與通用視圖之一一起使用。 我們可以通過將 ?JSONResponseMixin ?與 ?BaseDetailView ?混合來制作我們自己的 ?DetailView ?版本——(模板渲染行為之前的 ?DetailView ?已被混合):

from django.views.generic.detail import BaseDetailView

class JSONDetailView(JSONResponseMixin, BaseDetailView):
    def render_to_response(self, context, **response_kwargs):
        return self.render_to_json_response(context, **response_kwargs)

然后可以以與任何其他 ?DetailView ?相同的方式部署此視圖,具有完全相同的行為——除了響應(yīng)的格式。

您甚至可以混合一個(gè)能夠返回 HTML 和 JSON 內(nèi)容的 ?DetailView ?子類,具體取決于 HTTP 請(qǐng)求的某些屬性,例如查詢參數(shù)或 HTTP 表頭。 混合 ?JSONResponseMixin ?和 ?SingleObjectTemplateResponseMixin?,并覆蓋 ?render_to_response()? 的實(shí)現(xiàn),以根據(jù)用戶請(qǐng)求的響應(yīng)類型推遲到適當(dāng)?shù)某尸F(xiàn)方法:

from django.views.generic.detail import SingleObjectTemplateResponseMixin

class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView):
    def render_to_response(self, context):
        # Look for a 'format=json' GET argument
        if self.request.GET.get('format') == 'json':
            return self.render_to_json_response(context)
        else:
            return super().render_to_response(context)

由于 Python 解析方法重載的方式,對(duì) ?super().render_to_response(context)? 的調(diào)用最終會(huì)調(diào)用 ?TemplateResponseMixin ?的 ?render_to_response()? 實(shí)現(xiàn)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)