<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] 本節我們主要介紹如何自定義在第二部分提到過的admin后臺管理站點。 Django的admin站點是自動生成的、高度可定制的,它是Django相較其它Web框架獨有的內容,廣受歡迎。如果你覺得它不夠美觀,還有第三方美化版simpleUI。請一定不要忽略它,相信我,**它值得擁有**! <br /> ## **一、自定義后臺表單** 在前面的學習過程中,通過`admin.site.register(Question)`語句,我們在admin站點中注冊了Question模型。Django會自動生成一個該模型的默認表單頁面。如果你想自定義該頁面的外觀和工作方式,可以在注冊對象的時候告訴Django你的自定義選項。 下面是一個修改admin表單默認排序方式的例子。修改`polls/admin.py`的代碼:: ~~~ from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fields = ['pub_date', 'question_text'] admin.site.register(Question, QuestionAdmin) ~~~ 你只需要創建一個繼承`admin.ModelAdmin`的模型管理類,在其中進行一些自定義操作,然后將它作為第二個參數傳遞給`admin.site.register()`,第一個參數則是Question模型本身。 上面的修改讓`Date Publication`字段顯示在`Question`字段前面了(默認是在后面)。如下圖所示: ![](https://img.kancloud.cn/81/b4/81b4b454d27b54c63bd84ba79caeb099_1864x516.png) 對于只有2個字段的情況,效果看起來還不是很明顯,但是如果你有很多的字段,選擇一種直觀的符合我們人類習慣的排序方式則非常有用。 但是,當表單含有大量字段的時候,你更多的是想將表單劃分為一些字段的集合。 再次修改`polls/admin.py`: ~~~ from django.contrib import admin from .models import Question class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date']}), ] admin.site.register(Question, QuestionAdmin) ~~~ 字段集合`fieldsets`中每一個元組的第一個元素是該字段集合的標題。它讓我們的頁面看起來像下面的樣子: ![](https://img.kancloud.cn/19/15/19156e82f6e905bb2e6b7222d68c9910_1443x487.png) <br /> ## **二、添加關聯對象** 雖然我們已經有了Question的管理頁面,但是一個Question有多個Choices,如果想顯示Choices的內容怎么辦?有兩個辦法可以解決這個問題。第一個是像Question一樣將Choice注冊到admin站點,這很容易,修改`polls/admin.py`,增加下面的內容: ~~~ from django.contrib import admin from .models import Choice, Question # ... admin.site.register(Choice) ~~~ 重啟服務器,再次訪問admin頁面,就可以看到Choice條目了: ![](https://img.kancloud.cn/f2/37/f2370e3015eacfadce9cddc51dce6a0d_783x349.png) 點擊它右邊的add按鈕,進入“Add Choice”表單頁面,看起來如下圖: ![](https://img.kancloud.cn/a5/51/a5516a1e3dcd25f7678d8afe9386df30_768x316.png) 在這個表單中,Question字段是一個select選擇框,包含了當前數據庫中所有的Question實例。**Django在admin站點中,自動地將所有的外鍵關系展示為一個select框。** 在我們的例子中,目前只有一個question對象存在。 <br /> 請注意圖中的綠色加號,它連接到Question模型。每一個包含外鍵關系的對象都會有這個綠色加號。點擊它,會彈出一個新增Question的表單,類似Question自己的添加表單。填入相關信息點擊保存后,Django自動將該Question保存在數據庫,并作為當前Choice的關聯外鍵對象。白話講就是,新建一個Question并作為當前Choice的外鍵。 <br /> 但是實話說,這種創建方式的效率不怎么樣。如果在創建Question對象的時候就可以直接添加一些Choice,那會更好,這就是我們要說的第二種方法。下面,讓我們來動手試試。 <br /> 首先,刪除`polls/admin.py`中Choice模型對`register()`方法的調用。然后,編輯Question的內容,最后整個文件的代碼應該如下: ~~~ from django.contrib import admin from .models import Choice, Question class ChoiceInline(admin.StackedInline): model = Choice extra = 3 class QuestionAdmin(admin.ModelAdmin): fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ] inlines = [ChoiceInline] admin.site.register(Question, QuestionAdmin) ~~~ 上面的代碼相當于告訴Django,Choice對象將在Question管理頁面進行編輯,默認情況,請提供3個Choice對象的編輯區域。 <br /> 重啟服務器,進入“Add question”頁面,應該看到如下圖所示: ![](https://img.kancloud.cn/11/8c/118cf37c88ab4d75526d7896f5d4da01_1519x839.png) <br /> 在3個插槽的最后,還有一個`Add another Choice`鏈接。點擊它,又可以獲得一個新的插槽。如果你想刪除插槽,點擊它最右邊的灰色X圖標即可。 <br /> 注意,日期字段被疊藏起來了。 <br /> 這里還有點小問題。上面頁面中插槽縱隊排列的方式需要占據大塊的頁面空間,查看起來很不方便。為此,Django提供了一種扁平化的顯示方式,你僅僅只需要修改一下`ChoiceInline`繼承的類為`admin.TabularInline`替代先前的`StackedInline`類(其實,從類名上你就能看出兩種父類的區別)。 ~~~ # polls/admin.py class ChoiceInline(admin.TabularInline): #... ~~~ 重啟服務器,刷新一下頁面,你會看到類似表格的顯示方式: ![](https://img.kancloud.cn/81/77/8177b0c04b2d835e18d6644569f371e4_1460x739.png) 注意“DELETE”列,它可以刪除那些已有的Choice和新建的Choice。 <br /> ## **三、定制實例的列表頁面** Question的添加和修改頁面我們已經自定義得差不多了,下面讓我們來裝飾一下“實例列表”(change list)頁面,該頁面顯示了當前系統中所有的questions實例。 <br /> 默認情況下,該頁面看起來是這樣的: ![](https://img.kancloud.cn/e8/f4/e8f44536861ace1e46ed71cbdcfdd4c8_930x279.png) <br /> 通常,Django只顯示`__str()__`方法指定的內容。但是很多時候,我們可能要同時顯示一些別的內容。要實現這一目的,可以使用`list_display`屬性,它是一個由字段組成的元組,其中的每一個字段都會按順序顯示在頁面上,代碼如下: ~~~ # polls/admin.py class QuestionAdmin(admin.ModelAdmin): # ... list_display = ('question_text', 'pub_date', 'was_published_recently') ~~~ <br /> 額外的,我們把`was_published_recently()`方法的結果也顯示出來。現在,頁面看起來會是下面的樣子: ![](https://img.kancloud.cn/8e/60/8e602fd65aec3323e11137789d95c853_1525x230.png) 你可以點擊每一列的標題,來根據這列的內容進行排序。但是`was_published_recently`這一列除外,不支持這種根據函數輸出結果進行排序的方式。同時請注意,`was_published_recently`這一列的列標題默認是方法的名字,內容則是輸出的字符串表示形式。 <br /> 可以通過給方法提供一些屬性來改進輸出的樣式,如下面所示。注意**這次修改的是`polls/models.py`文件**,不要搞錯了!主要是增加了最后面三行內容: ~~~ # polls/models.py class Question(models.Model): # ... def was_published_recently(self): now = timezone.now() return now - datetime.timedelta(days=1) <= self.pub_date <= now was_published_recently.admin_order_field = 'pub_date' was_published_recently.boolean = True was_published_recently.short_description = 'Published recently?' ~~~ 重啟服務器(這個我就不再啰嗦了,大家心里都有數)。刷新頁面,效果如下: ![](https://img.kancloud.cn/f4/38/f4387943ac4460916d21a9fab1af1f7c_1514x256.png) 以上的定制功能還不是admin的全部,我們接著往下看! * * * 我們還可以使用`list_filter`屬性,**對顯示結果進行過濾**! 在`polls/admin.py`的QuestionAdmin中添加下面的代碼: ~~~ list_filter = ['pub_date'] ~~~ 再次刷新change list頁面,你會看到在頁面右邊多出了一個基于`pub_date`的過濾面板,如下圖所示: ![](https://img.kancloud.cn/70/b9/70b98c75b0fd3b8c8a3fb700ec3cc2f9_1532x339.png) <br /> 根據你選擇的過濾條件的不同,Django會在面板中添加不同的過濾選項。由于`pub_date`是一個`DateTimeField`,因此Django自動添加了這些選項:“Any date”, “Today”, “Past 7 days”, “This month”, “This year”。 順理成章的,讓我們再添加一些搜索的能力: ~~~ search_fields = ['question_text'] ~~~ <br /> 這會在頁面的頂部增加一個搜索框。當輸入搜索關鍵字后,Django會在`question_text`字段內進行搜索。只要你愿意,你可以使用任意多個搜索字段,Django在后臺使用的都是SQL查詢語句的LIKE語法,但是有限制的搜索字段有助于后臺的數據庫查詢效率。 ![](https://img.kancloud.cn/3b/b2/3bb27c4a42602b8bdeebc6a8d14dd6a6_1534x339.png) 其實,這個頁面還自動提供分頁功能,默認每頁顯示100條,只是我們的實例只有一個,囧,所以看不到分頁鏈接。 <br /> ## **四、定制admin整體界面** 很明顯,在每一個項目的admin頁面頂端都顯示`Django administration`是很可笑的,它僅僅是個占位文本。利用Django的模板系統,我們可以快速修改它。 ![](https://img.kancloud.cn/b3/dd/b3ddf268794673b11de5ddb8ed9b9bb3_1066x357.png) 在`manage.py`文件同級下創建一個`templates`目錄。然后,打開設置文件`mysite/settings.py`,在TEMPLATES條目中添加一個DIRS選項: ~~~ # mysite/settings.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], # 添加這一行 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] ~~~ DIRS是一個文件系統目錄的列表,是模板的搜索路徑。當加載Django模板時,會在DIRS中進行查找。這里面的目錄往往都是全局性的,區別于app自己內部的templates目錄。 **PS:模板的組織方式** 就像靜態文件一樣,我們可以把所有的模板都放在一起,形成一個大大的模板文件夾,并且工作正常。但是請一定不要這么做!強烈建議每一個模板都應該存放在它所屬應用的模板目錄內(例如polls/templates)而不是整個項目的模板目錄(templates),因為這樣每個應用才可以被方便和正確的重用。只有對整個項目有作用的模板文件才放在根目錄的templates中,比如admin界面。 <br /> 回到剛才創建的templates目錄中,再創建一個admin目錄,將`admin/base_site.html`模板文件拷貝到該目錄內。這個HTML文件來自Django源碼,它位于`django/contrib/admin/templates`目錄內。 (在我的windows系統中,它位于`C:\Python38\Lib\site-packages\django\contrib\admin\templates\admin`,請大家參考。事實上,如果你用的是Pycharm建立的虛擬環境,那么直接去`venv`目錄中尋找即可。) <br /> **Django的源代碼在哪里?** 如果你無法找到Django源代碼文件的存放位置,可以使用下面的命令: ~~~ $ python -c "import django; print(django.__path__)" ~~~ 編輯`base_site.html`文件,用你喜歡的站點名字替換掉`{{ site_header|default:_(’Django administration’) }}`(包括兩個大括號一起替換掉),看起來像下面這樣: ~~~ {% extends "admin/base.html" %} {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block branding %} <h1 id="site-name"><a href="{% url 'admin:index' %}">www.liujiangblog.com</a></h1> {% endblock %} {% block nav-global %}{% endblock %} ~~~ <br /> 在這里,我們使用的是硬編碼,強行改名為"www.liujiangblog.com"。但是在實際的項目中,你可以使用`django.contrib.admin.AdminSite.site_header`屬性,方便的對這個頁面title進行自定義。 <br /> 修改完后,刷新頁面,效果如下: ![](https://img.kancloud.cn/64/f2/64f2e9fca997eae47a34550eca6c7f35_1197x387.png) <br /> **提示**:所有Django默認的admin模板都可以被重寫,類似剛才重寫`base_site.html`模板的方法一樣,從源代碼目錄將HTML文件拷貝至你自定義的目錄內,然后修改文件。 <br /> **思考!** 讓我們來回顧一下這一小節的操作,其中包含了很多Django的原理。 1. admin后臺是一個內置的app,本質上和你的polls是一樣的 2. 直接修改Django源碼不是好的做法,所以我們不直接修改`base_site.html`模板 3. 我們復制了一份模板,在其中修改了站點名字 4. 為了讓修改的模板能夠自動替換原來的模板,我們創建了一個templates目錄 5. 這個新建的template目錄之所以能起作用,是因為我們在settings中配置了一個DIRS。 6. 當render需要`base_site.html`的時候,Django執行機制會首先去尋找DIRS中是否有`base_site.html`模板,結果找到了!于是它不再繼續尋找,所以admin源碼中的`base_site.html`模板被忽視了,成功達到了我們的目的。 <br /> ## **五、定制admin首頁** 默認情況下,admin首頁顯示所有`INSTALLED_APPS`內并在admin應用中注冊過的app,以字母順序進行排序。 <br /> 要定制admin首頁,你需要重寫`admin/index.html`模板,就像前面修改`base_site.html`模板的方法一樣,從源碼目錄拷貝到你指定的目錄內。編輯該文件,你會看到文件內使用了一個`app_list`模板變量。該變量包含了所有已經安裝的Django應用。你可以硬編碼鏈接到指定對象的admin頁面,使用任何你認為好的方法,用于替代這個`app_list`。 <br /> ## **六、源碼對照** 至此,Django教程的入門部分已經結束了。下面將`polls/admin.py`的全部代碼貼出來: ~~~ from django.contrib import admin from .models import Choice, Question class ChoiceInline(admin.TabularInline): model = Choice extra = 3 class QuestionAdmin(admin.ModelAdmin): list_display = ('question_text', 'pub_date', 'was_published_recently') fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), ] inlines = [ChoiceInline] list_filter = ['pub_date'] search_fields = ['question_text'] admin.site.register(Question, QuestionAdmin) ~~~ 整個投票項目mysite,在Pycharm中的文件組織結構如下圖所示,對比一下你自己的,看看是否一樣。 ![](https://img.kancloud.cn/65/f0/65f0bbf24efbb56d2b61d5a7b248e58a_375x786.png) <br /> 注意`2017.png`是展示用的背景圖,這個可以不一樣.... admin后臺管理站點可以定制得很強大,比如下面是博主站點的評論后臺,完全手工定制,非常實用! ![](https://img.kancloud.cn/28/7f/287fe71f400a1316e0b6a40dd6f8406c_1240x503.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看