Django管理器:class Manager
管理器是Django的模型進行數據庫查詢的接口,Django應用的每個模型都擁有至少一個管理器。默認情況下,Django為每個模型類添加一個名為objects的管理器,然而如果要將objects用於字段名稱或想使用其他名稱而不是objects來訪問管理器,可在每個模型類中重命名他們。自定義的管理器方法可以返回你想要的任何數據,而不需要返回一個查詢集。eg: models.py
# 文章模型
class Article(models.Model): title = models.CharField(max_length=50, verbose_name='文章標題') desc = models.CharField(max_length=50, verbose_name='文章描述') content = models.TextField(verbose_name='文章內容') click_count = models.IntegerField(default=0, verbose_name='點擊次數') is_recommend = models.BooleanField(default=False, verbose_name='是否推薦') date_publish = models.DateTimeField(auto_now_add=True, verbose_name='發布時間') user = models.ForeignKey(User, verbose_name='用戶') category = models.ForeignKey(Category, blank=True, null=True, verbose_name='分類') tag = models.ManyToManyField(Tag, verbose_name='標簽')
objects = ArticleManager() # 在模型中使用自定義的管理器
要實現文章歸檔,需要根據日期對文章這個模型類進行篩選:我們的目的是根據 ‘年-月’來歸並所有文章,此外若 17年8月沒有文章,則歸檔也不顯示17年8月這一空白歸檔。類似如下:
為實現根據年-月的文章篩選,可以早models.py中建立一個文章管理器,繼承自models.Manager:
class ArticleManager(models.Manager): def distinct_date(self): # 該管理器定義了一個distinct_date方法,目的是找出所有的不同日期 distinct_date_list = [] # 建立一個列表用來存放不同的日期 年-月 date_list = self.values('date_publish') # 根據文章字段date_publish找出所有文章的發布時間 for date in date_list: # 對所有日期進行遍歷,當然這里會有許多日期是重復的,目的就是找出多少種日期 date = date['date_publish'].strftime('%Y/%m 存檔') # 取出一個日期改格式為 ‘xxx年/xxx月 存檔’ if date not in distinct_date_list: distinct_date_list.append(date) return distinct_date_list
上文代碼建立的管理器需要在文章模型類加上語句:objects = ArticleManager() ,然后就可以調用 distinct_date 方法了: archive_list = Article.objects.distinct_date(),對比:
article_list = Article.objects.all() # 獲取所有文章,獲取到的是所有文章對象的一個列表
archive_list = Article.objects.distinct_date() # 文章歸檔 獲取到的列表格式為: xxx年/xxx月 存檔
我們要將 archive_list 這個列表顯示在html頁面中,所有需要一個for循環:在base.html中加入:
<div class="tuwen">
<h3>文章歸檔</h3>
<ul> {% for archive in archive_list %} <li>
<p><span class="tutime font-size-18"><a href='{% url 'archive' %}?year={{ archive | slice:":4" }}&month={{ archive | slice:"5:7" }}'>{{ archive }}</a></span></p>
</li> {% endfor %} </ul>
</div>
左圖即為html中的結果。 這里 {% url %} 這個模板標簽的作用是解析視圖函數對應的 URL 模式, 那么上文代碼中 ‘{% url 'archive' %}’ 是指解析views.py 中視圖函數archive對應的url模式。那么,每行歸檔文字都有了一個鏈接,格式為: http://127.0.0.1:8000/archive/?year=2015&month=02,{% url %}解析時會將year=2015和month=02 這兩個參數值傳遞到 views.py 請求中。 綜上,至此我們只實現了在base主頁面上顯示左圖,並且為各個歸檔賦予了鏈接,下一步我們需要為這個鏈接編寫相應的操作。
編寫urls.py 和 views.py
回顧上文的鏈接http://127.0.0.1:8000/archive/?year=2015&month=02, 我們看到鏈接為 archive, 所以需要對應的urls 和 視圖函數:
urls.py:
from blog.views import index, archive urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^$', index, name='index'), url(r'^archive/$', archive, name='archive'), # url路由,那么http://127.0.0.1:8000/archive/ 實現了,后面的參數咋辦?別急,在views中取出這個請求的參數 ]
views.py:
def archive(request):
year = request.GET.get('year', None) month = request.GET.get('month', None) # 取出兩個參數 year,month article_list = Article.objects.filter(date_publish__icontains=year+'-'+month) # 根據參數year,month進行過濾, 記得字段名+__icontains表大小寫不敏感的包含匹配
return render(request, 'archive.html', locals())
至此,我們將所有 http://127.0.0.1:8000/archive/?year=XXX&month=XX 都實現url解析,並篩選出來滿足year=XXX,month=XX的文章,下面我們需要在 archive.html 中將這些文章顯示出來。
歸檔頁面archive.html
在archive.html中加入文章歸檔顯示內容
<div class="topnews">
<h2>文章歸檔</h2> {% for article in article_list %} # 將XXX年XX月的所有文章進行展示 <div class="blogs">
<ul>
<h3><a href="/">{{ article.title }}</a></h3>
<p>{{ article.desc }}...</p>
<p class="autor"><span class="lm f_l">{% for tag in article.tag.all %}<a href="/">{{ tag.name }}</a> </span>{% endfor %}<span class="dtime f_l">{{ article.date_publish | date:'Y-m-d' }}</span><span class="viewnum f_r">瀏覽(<a href="/">{{ article.click_count }}</a>)</span><span class="pingl f_r">評論(<a href="/">{{ article.comment_set.all.count }}</a>)</span></p>
</ul>
</div> {% endfor %} </div>
注:下面也有分頁代碼
final:
注:另一種直接在views.archive中直接進行時間排序處理的方法,沒有利用管理器,較為簡潔。傳送門