模板(View)

后端渲染

1.模板的配置和渲染函數

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(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',
            ],
        },
    },
]
resp = render(request, 'index.html', {'foo': ...})

2.模板遇到變量名的查找順序。

  • 字典查找(如:foo['bar']
  • 屬性查找(如:foo.bar
  • 方法調用(如:foo.bar()
    • 方法不能有必須傳值的參數
    • 在模板中不能夠給方法傳參
    • 如果方法的alters_data被設置為True則不能調用該方法(避免誤操作的風險),模型對象動態生成的delete()save()方法都設定了alters_data = True.
  • 列表索引查找(如:foo[0]

3.模板標簽的使用。

  • {% if %} / {% else %} / {% endif %}
  • {% for %} / {% endfor %}
  • {% ifequal %} / {% endifequal %} / {% ifnotequal %} / {% endifnotequal %}
  • {# comment #} / {% comment %} / {% endcomment %}

4.過濾器的使用。

  • lower/upper/first/last/truncatewords/date/time/length/pluralize/center/ljust/rjust/cut/urlencode/default_if_none/filesizeformat/join/slice/slugify

5.模板的包含和繼承。

  • {% include %} / {% block %}
  • {% extends %}

6.模板加載器(后面優化部分會提到)

  • 文件系統加載器
TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR, 'templates')],
}]
  • 應用目錄加載器
TEMPLATES = [{
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'APP_DIRS': True,
}]

前端渲染

1.前端模板引擎:Handlebars/Mustache

2.前端MV*框架。

  • MVC - AngularJS
  • MVVM(Model - View - ViewModel) - Vue.js

其他視圖

1.MIME(多用途Internet郵件擴展)類型 - 告知瀏覽器傳輸的數據類型。

![1NBG$$A{38P[WJ)473M83.png](https://upload-images.jianshu.io/upload_images/14356833-a25c06ae114f2036.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

2.如何處置生成的內容(inline / attachment)。

>>> from urllib.parse import quote
>>>
>>> response['content-type'] = 'application/pdf'
>>> filename = quote('Python語言規范.pdf')
>>> filename
'Python%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83.pdf'
>>> response['content-disposition'] = f'attachment; filename="{filename}"'

提醒:URL以及請求和響應頭中的中文都應該處理成百分號編碼

3.生成CSV / Excel / 統計報表

  • 向瀏覽器傳輸二進制數據。
buffer = ByteIO()

resp = HttpResponse(content_type='...')
resp['Content_Disposition'] = 'attachement;filename='...''
resp.write(buffer.,getvalue())
def get_style(name,color=0,bold=False,italic=False):
  style = xlwt.XFStyle()
  font = xlwt.Font()
  font.name = name
  font.colour_index = color
  font.bold = bold
  font.italic = italic
  style.font = font
  return style

def export_emp_excel(request):
  # 創建Excel工作簿(使用三方庫xlwt)
  workbook = xlwt.Workbook()
  # 想工作簿中添加工作表
  sheet = workbook.add_sheet('員工詳細信息')
  # 設置表頭
  titles = ['編號','姓名','主管','職位','工資','部門名稱']
  for col, title in enumerate(titles):
    sheet.write(0, col, title, get_style('HanziPenSC-W3', 2, True))
  # 使用Django的ORM框架查詢員工數據
  emps =     Emp.objecets.all().select_related('dept').select_related('mgr')
 cols = ['no', 'name', 'mgr', 'job', 'sal', 'dept']
  # 通過嵌套的循環將員工表的數據寫入Excel工作表的單元格中
  for row, emp in enumerate(emps):
    for col, prop in enumerate(cols):
      val = getattr(emp, prop, '')
      if isinstace(val, (Dept, Emp)):
        val = val.name
      sheet.write(row + 1, col, val)
  # 將Excel文件的二進制數據寫入內存
  buffer = BytesIO()
  workbool.save(buffer)
  # 通過HttpResponse對象向瀏覽器輸出Excel文件
  resp = HttpResponse(buffer.getvalue())
  resp['content-type'] = 'application/msexcel'
  # 如果文件名中有中文需要處理成百分號編碼
  resp['content-disposition'] = 'attachment; filename = "detail.xls"'
  return resp
  • 大文件的流式處理:StreamingHttpResponse
def download_file(request):
  file_stream = open('...', 'rb')
  # 如果文件的二進制數據較大則最好用迭代器進行處理避免過多的占用服務器內存
  file_iter = iter(lambda: file_stream.read(4096), b'')
  resp = StreamingHttpResponse(file_iter)
  #中文文件名要處理成百分號編碼
  filename = quote('...', 'uft-8')
  resp['Content-Type'] = '...'
  resp['Content-Disposition'] = f'attachment; 
  filename = "{filename}"'
  return resp

說明:如果需要生成PDF文件,可以阿娜黃reportlab。另外,使用StreamingHttpResponse只能減少內存的開銷,但是如果下載一個大文件會導致一個請求長時間占用服務器資源,比較好的做法還是把報表提前生成好(可以考慮使用定時任務),放在靜態資源服務器或者是云存儲服務器上以訪問靜態資源的方式訪問

  • EChartsChart.js
    • 思路:后端只提供JSON格式的數據,前端JavaScript渲染生成圖表。
def get_charts_data(request):
    """獲取統計圖表JSON數據"""
    names = []
    totals = []
    # 通過connections獲取指定數據庫連接并創建游標對象
    with connections['backend'].cursor() as cursor:
        # 在使用ORM框架時可以使用對象管理器的aggregate()和annotate()方法實現分組和聚合函數查詢
        # 執行原生SQL查詢(如果ORM框架不能滿足業務或性能需求)
        cursor.execute('select dname, total from vw_dept_emp')
        for row in cursor.fetchall():
            names.append(row[0])
            totals.append(row[1])
    return JsonResponse({'names': names, 'totals': totals})
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>統計圖表</title>
    <style>
        #main {
            width: 600px;
            height: 400px;
        }
    </style>
</head>
<body>
    <div id="main"></div>
    <script src="https://cdn.bootcss.com/echarts/4.2.0-rc.2/echarts.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script>
        var myChart = echarts.init($('#main')[0]);
        $.ajax({
            'url': 'charts_data',
            'type': 'get',
            'data': {},
            'dataType': 'json',
            'success': function(json) {
                var option = {
                    title: {
                        text: '員工分布統計圖'
                    },
                    tooltip: {},
                    legend: {
                        data:['人數']
                    },
                    xAxis: {
                        data: json.names
                    },
                    yAxis: {},
                    series: [{
                        name: '人數',
                        type: 'bar',
                        data: json.totals
                    }]
                };
                myChart.setOption(option);
            },
            'error': function() {}
        });
    </script>
</body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在控制器的方法中調用如下方法: $this -> display();//模板名稱與當前操作方法的名稱一致 $th...
    hello大象閱讀 57評論 0 0
  • 概要 64學時 3.5學分 章節安排 電子商務網站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,276評論 0 3
  • github地址,歡迎大家提交更新。 express() express()用來創建一個Express的程序。ex...
    Programmer客棧閱讀 2,573評論 0 1
  • 《緣故緣故》 含淚而笑,因風起航。 緣故緣故,境遇如此。 我本候鳥,茫然回眸。 終等那時,北有佳人。 一封書...
    Ulia閱讀 539評論 0 7
  • 最近在追劇《知否知否,應是綠肥紅瘦》,我不追星,也不太看娛樂新聞,但是對趙麗穎一直是有好感,喜歡她的清秀模樣和清澈...
    欣欣然也閱讀 606評論 0 2