Django 將views.py檔案中有的資料寫成全域性變數 這樣每個函式都可以用到
阿新 • • 發佈:2018-12-26
在Django中,有時幾個頁面中要顯示的資料一樣,或者說一個頁面中,點選連結只會重新整理其中一部分內容,其他的不變。
這樣,我們就可以將相同的、需要渲染在模板中的資料,寫成全域性的,這樣減少程式碼的重複書寫
例如:
當點選某一個月份文章歸檔時,只有文章那一塊會發生變化,其他都不變化
然後,我們就需要將其他的做成全域性的。
在views.py中
def global_params(request): # 該函式中用於儲存一些全域性變數,每個/多個檢視函式都要使用並且程式碼都沒有發生變化的變數。所以可以對這些重複性的程式碼進行優化,直接設定為全域性變數,不用在渲染模版的時候每次都傳遞這些變數。 # 查詢所有分類資訊 category_list = Category.objects.all() # 查詢所有廣告資訊 ad_list = Ad.objects.all() archive_list = Article.objects.archive_date(article_list=Article.objects.all()) # 評論排行 # [{'article': 1, 'count': 3},{}] article_dict_list = Comment.objects.values('article').annotate(count=Count('article')).order_by('-count') # 從查詢結果集合QuerySet中,根據article的id,取出這個文章的Model物件。 result_list = [Article.objects.get(id=article_dict['article']) for article_dict in article_dict_list] if len(result_list) > 6: result_list = result_list[:6] # 瀏覽排行 # 三目運算子:a = if b>c? 10:20 # if條件成立,則取Article.objects.all().order_by('-click_num')[:6]的值;if條件不成立,則取else:Article.objects.all().order_by('-click_num')的值; click_list = Article.objects.all().order_by('-click_num')[:6] if len(Article.objects.all()) >= 6 else Article.objects.all().order_by('-click_num') # 標籤雲 tag_list = Tag.objects.all() return { 'category_list': category_list, 'ad_list': ad_list, 'archive_list': archive_list, 'comment_list': result_list, 'click_list': click_list, 'tag_list': tag_list } def process_paginator(request, article_list): paginator = Paginator(article_list, 1) try: page_number = int(request.GET.get('page', '1')) page = paginator.page(page_number) except (PageNotAnInteger, EmptyPage, InvalidPage): page = paginator.page(1) return page def index(request): # 所有文章資訊 article_list = Article.objects.all() page = process_paginator(request, article_list) title = '最新文章' # 文章歸檔: # 第一種方法就是定義一個普通的函式archive_article。 # archive_list = archive_article(article_list) # 第二種方式:通過自定義管理器Manager方法實現,通過這種方法,可以實現Article.objects.xxx()的呼叫方式; # 1. 在models.py中自定義一個管理器(一定要繼承於內建的Manager類。); # 2. 在需要使用的Model類中,註冊這個管理器,那麼這個Model就可以使用這個管理器方法了; # archive_list = Article.objects.archive_date(article_list=article_list) return render(request, 'index.html', locals()) def archive(request, year, month): # 查詢釋出日期中含有:2018-10 的資料 article_list = Article.objects.filter(date_publish__icontains=year+'-'+month) page = process_paginator(request, article_list) return render(request, 'index.html', locals())
其中的global_params函式裡面寫的都是下面的函式渲染模板都需要用到的,那麼除了將這些資料單獨寫在一個函式之外,還需要在settings.py中設定:
哪個APP下的哪個檔案下的哪個函式是全域性的
這個實現了
其中,在global_params函式中,有一點,將對文章的建立時間的處理封裝成了Article類的物件
能有Article.objects.呼叫的都是all() get() filter() 是Django封裝好的,可直接呼叫。但是我們也可以自己封裝一個,使其能夠Article,objects…呼叫
在models.py中封裝:
class ArticleManager(models.Manager): def archive_date(self, article_list): archive_list = [] # 需要獲取所有的文章model物件。 for article in article_list: # 將每一個文章的釋出日期都獲取出來,按照'%Y/%m'進行格式化 pub_date = article.date_publish.strftime('%Y/%m') if pub_date not in archive_list: # 如果這個時間字串不在article_list這個列表中,就把這個年月新增進去 archive_list.append(pub_date) return archive_list class Article(models.Model): objects = ArticleManager() title = models.CharField(max_length=50, verbose_name='文章標題') desc = models.CharField(max_length=50, verbose_name='文章簡介') content = models.CharField(max_length=255, verbose_name='文章內容') click_num = models.IntegerField(verbose_name='點選量', default=0, editable=True) comment_num = models.IntegerField(verbose_name='評論量', default=0, editable=True) date_publish = models.DateTimeField(auto_now_add=True, verbose_name='釋出時間') tag = models.ManyToManyField(Tag, verbose_name='所屬標籤') category = models.ForeignKey(Category, verbose_name='所屬分類', on_delete=models.DO_NOTHING, blank=True, null=True)
注意兩點:一、封裝的類要繼承自models.Manager
二、在要進行Article.objects.呼叫的Article類中,寫上
objects = ArticleManager()
這樣,才可以,在views.py中寫:Article.objects.archive_date()
archive_date是封裝那個類中的函式
還有,注意傳參,一定要一致