1. 程式人生 > >Django 將views.py檔案中有的資料寫成全域性變數 這樣每個函式都可以用到

Django 將views.py檔案中有的資料寫成全域性變數 這樣每個函式都可以用到

在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是封裝那個類中的函式
還有,注意傳參,一定要一致