1. 程式人生 > >Django流程(2)

Django流程(2)

切換到建立專案的目錄  cd C:\Users\admin\Desktop\DjangoProject
建立名為project的專案命令  django-admin startproject project
            注:所有路徑不要有中文
            切換到目錄cd C:\Users\admin\Desktop\DjangoProject\project
目錄層級說明:manage.py  一個命令列工具,可以讓我們用多種方式對Django專案進行互動
             __init__.py 一個空檔案,它告訴Python這個目錄應該被看做一個包
             settings.py 專案的配置檔案(主要處理檔案)
             urls.py     專案的url宣告 (主要處理檔案)
             wsgi.py     專案與WSGI相容的Web伺服器入口
配置資料庫   Django預設使用SQLite資料庫
            在settings.py檔案中通過DATABASES選項進行資料庫配置
配置MySQL    Python3.x中安裝的是PyMySQL
            在__init__.py檔案中寫入兩行程式碼import pymysql
                                        pymysql.install_as_MySQLdb()
    以資料庫sunck為例進行示範:對settings.py中的DATABASES進行設定
            DATABASES = {
                'default': {
                    'ENGINE': 'django.db.backends.mysql',
                    'NAME': "sunck",
                    'USER': "root",
                    'PASSWORD': "admin123",
                    'HOST': "localhost",
                    'PORT': "3306"
                }
            }
建立應用--在一個專案中可以建立多個應用,每個應用進行一種業務處理
        開啟CMD,進入project(目錄名)的目錄下,輸入命令建立名為myApp的app:
            python manage.py startapp myAPP
myAPP目錄說明
    admin.py    進行站點配置
    models.py   建立模型
    views.py    建立檢視
啟用應用  在settings.py檔案中,將myApp應用加入到INSTALLED_APPS選項中
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myApp',
    ]
定義模型 概述:有一個數據表就對應有一個模型
        在models.py檔案中定義模型
            引入:from django.db import models
            模型類要繼承models.Model類
            示例:
                class Grades(models.Model):
                    gname = models.CharField(max_length=20)
                    gdate = models.DateTimeField()
                    ggirlnum = models.IntegerField()
                    gboynum = models.IntegerField()
                    isDelete = models.BooleanField(default=False)

                class Students(models.Model):
                    sname = models.CharField(max_length=20)
                    sgender = models.BooleanField(default=True)
                    sage = models.IntegerField()
                    scontend = models.CharField(max_length=20)
                    isDelete = models.BooleanField(default=False)
                    sgrade = models.ForeignKey("Grades", on_delete=models.CASCADE,)
            說明:
                不需要定義主鍵,在生成時自動新增,並且值為自動增加
在資料庫中生成資料表
    生成遷移檔案
        執行 python manage.py makemigrations    在migrations目錄下生成一個遷移檔案,此時資料庫中還沒有生成資料表
    執行遷移
        執行 python manage.py migrate           相當於執行MySQL語句建立了資料表

測試資料操作
進入到python shell
    執行 python manage.py shell
引入包
    from myApp.models import Grades, Students
    from django.utils import timezone
    from datetime import *
查詢所有資料
    類名.objects.all()
    示例: Grades.objects.all()
新增資料
    本質:建立一個模型類的物件例項
    示例:CMD視窗下:
        grade1 = Grades()
        grade1.gname = "python04"
        grade1.gdate = datetime(year=2017, month=7, day=17)
        grade1.ggirlnum = 3
        grade1.gboynum = 70
        grade1.save()
檢視某個物件
    類名.objects(pk=索引號)
    示例:
        Grades.objects.get(pk=2)
        Grades.objects.all()
修改某個資料
    模型物件屬性 = 新值
    示例:
        grade2.gboynum = 60
        grade2.save()
刪除資料
    模型物件.delete()
    grade2.delete()
    注意:這是物理刪除,資料庫中的相應資料被永久刪除
關聯物件
    示例:
        stu = Students()
        stu.sname = "Xue Yanmei"
        stu.sgender = False
        stu.sage = 20
        stu.scontend = "I am Xue Yanmei"
        stu.sgrade = grade1
        stu.save()
    獲得關聯物件的集合
        需求:獵取python04班級的所有學生
             物件名.關聯的類名小寫_set.all()
             示例:grade1.students_set.all()
        需求:建立曾志偉,屬於python04班級
            示例:
                stu3 = grade1.students_set.create(sname=u'Zhen Zhiwei',sgender=True,scontend=u"I am Zhen Zhiwei",sage=45)
            注意:這樣建立的資料直接被新增到了資料庫當中。
啟動伺服器:
    格式:python manage.py runserver ip:port
    注意:ip可以不寫,不寫代表本機ip
    埠號預設是8000
    python manage.py runserver
    說明:
        這是一個純python編寫的輕量級web伺服器,僅僅在開發測試中使用這個
Admin站點管理:
    概述:
        內容釋出:負責新增,修改,刪除內容的
        公告訪問
    配置Admin應用:
        在settings.py檔案中的INSTALLED_APPS中新增'django.contrib.admin',
        這條預設是新增好的。
    建立管理員使用者:
        在專案目錄下執行 python manage.py createsuperuser
        依次輸入賬號名,郵箱,密碼即可完成使用者建立
    登陸:
        http://127.0.0.1:8000/admin/
    漢化:
        把project\settings.py
        中作如下設定:LANGUAGE_CODE = 'zh-Hans'
                     TIME_ZONE = 'Asia/Shanghai'
管理資料表:
    修改 myAPP\admin.py 如下:
        from django.contrib import admin
        # Register your models here.
        from .models import Grades, Students
        # 註冊
        admin.site.register(Grades)
        admin.site.register(Students)
    自定義管理頁面:
        屬性說明
            # 列表頁屬性
            list_display = [] # 顯示欄位設定
            list_filter = [] # 過濾欄位設定
            search_fields = [] # 搜尋欄位設定
            list_per_page = [] # 分頁設定
            # 新增,修改頁屬性
            fields = [] # 規定屬性的先後順序
            fieldsets = [] # 給屬性分組 注意:fields與fieldsets不能同時使用
        屬性示例:
            # 列表頁屬性
            list_display = ['pk', 'gname', 'gdate', 'ggirlnum', 'gboynum', 'isDelete']
            list_filter = ['gname']
            search_fields = ['gname']
            list_per_page = 5
            # 新增,修改頁屬性
            # fields = ['ggirlnum', 'gboynum', 'gname', 'gdate', 'isDelete']
            fieldsets = [
                ("num",{"fields":['ggirlnum', 'gboynum']}),
                ("base", {"fields":["gname", "gdate", "isDelete"]}),
            ]
        關聯物件:需求:在建立一個班級時可以直接新增幾個學生
            class StudentsInfo(admin.TabularInline):# 可選引數admin.StackedInline
                model = Students
                extra = 2
            class GradesAdmin(admin.ModelAdmin):
                inlines = [StudentsInfo]
        布林值顯示問題示例:
            class StudentsAdmin(admin.ModelAdmin):
                def gender(self):
                    if self.sgender:
                        return "男"
                    else:
                        return "女"
                # 設定頁面列的名稱
                gender.short_description = "性別"
                list_display = ['pk', 'sname', 'sage', gender,
                                'scontend', 'sgrade', 'isDelete']
                list_per_page = 10
            admin.site.register(Students, StudentsAdmin)
        執行按鈕位置:
            class StudentsAdmin(admin.ModelAdmin):
                ...snip...
                actions_on_top = False
                actions_on_bottom = True
            admin.site.register(Students, StudentsAdmin)
        使用裝飾器完成註冊:
            @admin.register(Students)
                class StudentsAdmin(admin.ModelAdmin):
                    def gender(self):
                    ...snip...
                    actions_on_top = False
                    actions_on_bottom = True
檢視的基本使用
    概述:
        在Django中,檢視是對web請求進行迴應
        檢視就是一個python函式,在views.py檔案中定義。
    定義檢視:
        示例:在myApp\views.py中寫入
            from django.shortcuts import render
            # Create your views here.
            from django.http import HttpResponse
            def index(request):
                return HttpResponse("Sunck is a good man")
    配置url:方法一:path方法:
        修改project目錄下的urls.py檔案:
            from django.contrib import admin
            from django.urls import path, include
            urlpatterns = [
                path('admin/', admin.site.urls),
                path('', include('myApp.urls')),
            ]
        在myApp應用目錄下建立urls.py檔案:
            from django.urls import path, include
            from . import views
            urlpatterns = [
                path('',views.index),
            ]
    配置url:方法二:url方法:
        修改project目錄下的urls.py檔案:
            from django.contrib import admin
            from django.conf.urls import url,include
            urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^', include('myApp.urls')),
            ]
        在myApp應用目錄下建立urls.py檔案:
            from django.conf.urls import url
            from . import views
            urlpatterns = [
                url(r'^$', views.index),
            ]
模板的基本使用:
    概述:模板是HTML頁面,可以根據檢視中傳遞過來的資料進行填充
    建立模板:
        建立templates目錄,在目錄下建立對應專案的模板目錄(project/templates/myApp)
    配置模板路徑:
        修改settings.py檔案下的TEMPLATES下的'DIRS'為'DIRS': [os.path.join(BASE_DIR, 'templates')],
    定義grades.html與students.html模板:
        在templates\myApp\目錄下建立grades.html與students.html模板檔案
        模板語法:
            {{輸出值,可以是變數,也可以是物件,屬性}}
            {%執行程式碼段%}
    http://127.0.0.1:8000/grades
        寫grades.html模板:
            <!doctype html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport"
                      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
                <meta http-equiv="X-UA-Compatible" content="ie=edge">
                <title>班級資訊</title>
            </head>
            <body>
                <h1>班級資訊列表</h1>
                <ul>
                    <!--[python04, python05, python06]-->
                    {%for grade in grades%}
                    <li>
                        <a href="#">{{grade.gname}}</a>
                    </li>
                    {%endfor%}
                </ul>
            </body>
            </html>
        定義檢視:myApp\views.py
            from .models import Grades
            def grades(request):
                # 去模板裡取資料
                gradesList = Grades.objects.all()
                # 將資料傳遞給模板,模板再渲染頁面,將渲染好的頁面返回給瀏覽器
                return render(request, 'myApp/grades.html', {"grades": gradesList})
        配置url:myApp\urls.py
        urlpatterns = [
            url(r'^$', views.index),
            url(r'^(\d+)/(\d+)$', views.detail),
            url(r'^grades/', views.grades)
        ]
    http://127.0.0.1:8000/students
        寫students.html模板
            <!doctype html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport"
                      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
                <meta http-equiv="X-UA-Compatible" content="ie=edge">
                <title>學生頁面</title>
            </head>
            <body>
                <h1>學生資訊列表</h1>
                <ul>
                    {%for student in students%}
                    <li>
                        {{student.sname}}--{{student.scontend}}
                    </li>
                    {%endfor%}
                </ul>
            </body>
            </html>
        定義檢視:myApp\views.py
            from .models import Students
            def students(request):
                studentsList = Students.objects.all()
                return render(request, 'myApp/students.html', {"students": studentsList})
        配置url:myApp\urls.py
            urlpatterns = [
            url(r'^$', views.index),
            url(r'^(\d+)/(\d+)$', views.detail),
            url(r'^grades/', views.grades),
            url(r'^students/', views.students),
        ]
    需求:點選班級,顯示對應班級的學生名字
        執行不正常https://www.bilibili.com/video/av17879644/?p=12






Django流程梳理
    建立工程:執行 django-admin startproject 工程名
    建立專案:執行 python manage.py startapp 專案名稱
    啟用專案:修改 settings.py中的INSTALLED_APPS
    配置資料庫:
        修改__init__.py檔案
        修改settings.py檔案中的DATABASES
    建立模型類:在專案目錄下的models.py檔案中建立
    生成遷移檔案:執行python manage.py makemigrations
    執行遷移:執行python manage.py migrate
    配置站點:略
    建立模板目錄/專案模板目錄
    在settings.py中的TEMPLATES新增templates路徑
    在工程目錄下(project)修改urls.py
    在專案目錄下建立urls.py


使用他人Django程式碼需要的簡易修改:
1.在settings.py中修改資料庫名
2.在settings.py中修改資料庫密碼
3.刪除由內向外檔案(在對應目錄裡滑鼠右鍵刪除)
4.在資料庫中建立對應第一步的資料庫(自己在SQL中建立)
5.執行生成遷移檔案
6.執行遷移
7.啟動服務
8.瀏覽器測試


Django模型
    Django對各種資料庫提供了很好的支援,Django為這些資料庫提供了統一的呼叫API
    我們可以根據不同的業務需求選擇不同的資料庫。
    配置資料庫
        修改工程目錄下的__init__.py檔案
            import pymysql
            pymysql.install_ad_MySQLdb()
        修改settings.py檔案中的DATABASES
    開發流程
        配置資料庫
        定義模型類:一個模型都在資料庫中對應一張資料庫表
        生成遷移檔案
        執行遷移生成資料表
        使用模型類進行增刪改查
    ORM
        概述:物件-關係-對映
        任務:
            根據物件的型別生成表結構
            將物件,列表的操作轉換成SQL語句
            將SQL語句查詢到的結果轉換為物件,列表
        優點:
            極大的減輕了開發人員的工作量,不需要面對因資料庫的變更而修改程式碼的問題
    定義模型
        模型,屬性,表,欄位之間的關係
            一個模型類在資料庫中對應一張表,在模型類中定義的屬性,對應該模型對照表中的一個欄位
        定義屬性:見下文
        建立模型類
        元選項
            在模型類中定義Meta類,用於設定元資訊
            示例:
                class Meta:
                    db_table = "students"
                    ordering = ['id']
            db_table
                定義資料表名,推薦用小寫字母,資料表名預設為專案名小寫_類名小寫
            ordering
                物件的預設排序欄位,獲取物件的列表時使用
                示例:
                    ordering['id'] id按升序排列
                    ordering['-id'] id按降序排列
                注意:排序會增加資料庫開銷
    模型成員
        類屬性
            隱藏類屬性objects:
                是Manager型別的一個物件,作用是與資料庫進行互動
                當定義模型類時沒有指定管理器,則Django為模型建立一個名為objects的管理器
            自定義管理器示例:
                定義stuObj管理器:
                    stuObj = models.Manager()
                當為模型指定模型管理器,Django就不再為模型類生成objects模型管理器了。
            自定義管理器Manager類
                模型管理器是Django的模型進行與資料庫互動的視窗,一個模型可以有多個模型管理器
                作用:
                    向管理器類中新增額外的方法
                    修改管理器返回的原始查詢集
                        通常會重寫get_queryset()方法
                程式碼示例:
                    class StudentsManager(models.Manager):
                        def get_queryset(self):
                            return super(StudentsManger, self).get_queryset().filter(isDelete=False)

                    class Students(model.Moder):
                        # 自定義模型管理器
                        # 當自定義模型管理器,objects就不存在了
                        stuObj = models.Manger()
                        stuObj2 = StudentsManager()

        建立物件
            目的:向資料庫中新增資料
            當建立物件時,django不會對資料庫進行讀寫操作,當呼叫save()方法時才與資料庫互動,將物件儲存在資料庫表中。
            注意:
                __init__方法已經在父類models.Model中使用,在自定義的模型中無法使用。
            方法:
                在模型類中增加一個類方法,示例如下:
                    class Students(model.Moder):
                        ...snip...
                         @classmethod
                        def createStudent(cls, name, age, gender, contend,
                                          grade,lastT, createT, isD=False):
                            stu = cls(sname=name, sage=age, sgender=gender,
                                        scontend=contend, sgrade=grade, lastTime=lastT, createTime=createT,
                                        isDelete=isD)
                            return stu
                在自定義管理器中新增一個方法,示例如下:
                    class StudentsManager(models.Manager):
                        def get_queryset(self):
                            return super(StudentsManager, self).get_queryset().filter(isDelete=False)
                        def createStudent(self, name, age, gender, contend, grade, lastT, createT, isD=False):
                            stu = self.model()
                            # print(type(grade))
                            stu.sname = name
                            stu.sage = age
                            stu.sgender = gender
                            stu.scontend = contend
                            stu.sgrade = grade
                            stu.lastTime = lastT
                            stu.createTime = createT
                            return stu
        模型查詢
            概述
                查詢集表示從資料庫獲取的物件的集合
                查詢集可以有多個過濾器
                過濾器就是一個函式,基於所給的引數限制查詢集結果
                從SQL角度來說,查詢集和select語句等價,過濾器就像where條件
            查詢集
                在管理器上呼叫過濾器方法返回查詢集
                查詢集經過過濾器篩選後返回新的查詢集,所以可以寫成鏈式呼叫
                惰性執行
                    建立查詢集不會帶來任何資料庫的訪問,直到呼叫資料庫時,才會訪問資料
                直接訪問資料的情況:
                    迭代
                    序列化
                    與if合用
                返回查詢集的方法稱為過濾器
                    all():返回查詢集中的所有資料
                    filter():保留符合條件的資料
                        filter(鍵=值)
                        filter(鍵=值,鍵=值)
                        filter(鍵=值).filter(鍵=值)   且的關係
                    exclude():過濾掉符合條件的
                    order_by():排序
                    values():一條資料就是一個字典,返回一個列表
                    get()
                        返回一個滿足條件的物件
                        注意:
                            如果沒有找到符合條件的物件,會引發模型類.DoesNotExist異常
                            如果找到多個物件,會引發模型類MultipleObjectsReturned異常
                    count():返回查詢集中物件的個數
                    first():返回查詢集中第一個物件
                    last():返回查詢集中最後一個物件
                    exits():判斷查詢集中是否有資料,如果有資料返回 True,否則返回 False.
                限制查詢集
                    查詢集返回列表,可以使用下標的方法進行限制,等同於sql中的limit語句
                    注意:下標不能是負數
                    示例:studentsList = Students.stuObj2.all()[0:5]
                查詢集的快取
                    概述:
                        每個查詢集都包含一個快取,來最小化對資料庫的訪問
                        在新建的查詢集中,快取首次為空,第一次對查詢集求值,會發生資料快取,Django會將查詢出來的資料做一個快取,並返回查詢結果。
                        以後的查詢直接使用查詢集的快取
                欄位查詢
                    概述
                        實現了sql中的where語句,作為方法filter(),exclude(),get()的引數
                        語法:屬性名稱__比較運算子=值
                        外來鍵:屬性名稱_id
                        轉義:類似sql中的like語句
                             like有關情況看我哥他%是為了匹配點位,匹配資料中的%使用(where like "\%")
                             filter(sname__contains="%")
                    比較運算子
                        exact:判斷,大小寫敏感
                            filter(isDelete=False)
                        contains:是否包含,大小寫敏感
                            studentsList = Students.stuObj2.filter(sname__contains="孫")
                        startswith,endswith:以value開頭或結尾,大小寫敏感
                        以上四個在前面加上i,就表示不區分大小寫iexact,icontains,istartswith,iendswith
                        isnull,isnotnull
                            是否為空
                            filter(sname__isnull=False)
                        in:是否包含在範圍內
                        gt大於,gte大於等於,lt小於,lte小於等於
                        year,month,day,week_day,hour,minute,second
                            studentsList = Students.stuObj2.filter(lastTime__year=2017)
                        跨關聯查詢
                            處理join查詢
                                語法:
                                    模型類名__屬性名__比較運算子
                                    # 描述中帶有‘薛延美’這三個字的資料是屬於哪個班級的
                                    grade = Grades.objects.filter(students__scontend__contains='薛延美')
                                    print(grade)
                            查詢快捷pk代表的主鍵
                        聚合函式
                            使用aggregate函式返回聚合函式的值
                            Avg
                            Count
                            Max
                                maxAge = Student.stuObj2.aggregate(Max('sage'))
                                maxAge為最大的sage。
                            Min
                            Sum
                        F物件
                            可以使用模型的A屬性與B屬性進行比較
                            from django.db.models import F,Q
                            def grades1(request):
                                g = Grades.objects.filter(ggirlnum__gt=F('gboynum'))
                                print(g)
                                # [<Grades: python02>,<Grades: python03>]
                                return HttpResponse("OOOOOOOo")
                            支援F物件的算術運算
                                g = Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)
                        Q物件
                            概述:過濾器的方法的關鍵字引數,條件為And模式
                            需求:進行or查詢
                            解決:使用Q物件
                                def students4(request):
                                    studentsList = Students.stuObj2.filter(Q(pk__lte=3) | Q(sage__gt=50))
                                    return render(request, 'myApp/students.html', {"students": studentsList})
                                只有一個Q物件的時候,就是用於正常匹配條件
                                studentsList = Students.stuObj2.filter(~Q(pk__lte=3))
                                ~Q是取反


定義屬性
    概述:
        django根據屬性的型別確定以下資訊
            當前選擇的資料庫支援欄位的型別
            渲染管理表單時使用的預設html控制元件
            在管理站點最低限度的驗證

        django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如
        果使用選項設定某屬性為主鍵列後,則django不會再生成預設的主鍵列

        屬性命名限制
            遵循識別符號規則,且變數不能與Python保留字相同
            由於django的查詢方式,不允許使用連續的下劃線

    庫
        定義屬性時,需要欄位型別,欄位型別被定義在django.db.models.fields目錄下,
        為了方便使用,被匯入到django.db.models中

        使用方式
            匯入: from django.db import models
            通過 models.Field建立欄位型別的物件,賦值給屬性

    邏輯刪除
        對於重要型別都做邏輯刪除,不做物理刪除,實現方法是定義idDelete屬性,
        型別為BooleanField,預設值為False

    欄位型別
        autoField
            一個根據實際ID自動增長的IntegerField,通常不指定,
            如果不指定,一個主鍵欄位將自動新增到模型中

        CharField(max_length=字元長度)
            字串,預設的表彰樣式是TextInput

        TextField
            大文字欄位,一般超過4000時使用,預設的表單控制元件是Textarea

        IntegerField
            整數

        DecimalField(max_digits=None, decimal_places=None)
            使用Python的Decimal例項表示的十進位制浮點數
            引數說明
                DecimalField.max_digits
                    位數總數
                DecimalField.decimal_places
                    小數點後的數字位置

        FloatField
            使用Python的float例項來表示的浮點數

        BooleanField
            True/False 欄位,此欄位的預設表彰控制是CheckboxInput

        NullBooleanField
            支援 Null, True, False 三種值

        DateField([auto_now=False, auto_now_add=False])
            使用Python的datetime.date例項表示的日期
            引數說明:
                DateField.auto_now
                    每次儲存物件時,自動設定該欄位為當前時間,用於“最後一次修改”
                    的時間戳,它總是使用當前日期,預設為 False
                DateField.auto_now_add
                    當前物件第一次被建立時自動設定當前時間,用於建立的時間戳,
                    它總是使用當前日期,預設為 False
            說明
                該欄位預設對應的表單控制元件是一個TextInput.在管理員站點添加了一個
                JavaScript寫的日曆控制元件,和一個“Today”的快捷按鈕,包含了一個額外
                的invalid_date錯誤訊息鍵
            注意
                auto_now_add, auto_now, and default 這些設定是相互排斥的,他們之間
                的任何組合將會發生錯誤的結果

        TimeField
            使用Python的datetime.time例項表示的時間,引數同DateField

        DateTimeField
            使用Python的datetime
            datetime例項表示的日期和時間,引數同DateField

        FileField
            一個上傳檔案的欄位

        ImageField
            繼承了FileField的所有屬性和方法,但對上傳的物件進行校驗,
            確保它是一個有效的image

    欄位選項
        概述
            通過欄位選項,可以實現對欄位的約束
            在欄位物件中通過關鍵字引數指定

        null
            如果為True,Django將空值以NULL儲存在資料庫中,預設值為 False

        blanke
            如果為True,則該欄位允許為空白,預設值為 False

        注意
            null是資料庫範疇的概念,blank是表彰驗證範疇的概念

        db_column
            欄位的名稱,如果未指定,則使用屬性的名稱

        db_index
            若值為 True,則在表中會為此欄位建立索引

        default
            預設值

        primary_key
            若為 True,則該欄位會成為模型的主鍵欄位

        unique
            如果為 True,這個欄位在表中必須有唯一值

    關係
        分類
            ForeignKey:一對多,將欄位定義在多的端中
            ManyToManyField:多對多,將欄位定義在兩端中
            OneToOneField:一對一,將欄位定義在任意一端中

        用一訪問多
            格式
                物件.模型類小寫_set
            示例
                grade.students_set

        用一訪問一
            格式
                物件.模型類小寫
            示例
                grade.studnets

        訪問id
            格式
                物件.屬性_id
            示例
                student.sgrade_id


檢視
    概述:
        作用:檢視接收web請求,並響應web請求
        本質:檢視就是python中的一個函式
        響應:
            響應過程:
                使用者在瀏覽器中輸入網址www.sunck.wang/sunck/index.html
                ---網址--->
                django獲取網址資訊,去掉IP與埠號,網址變成:sunck/index.html
                ---虛擬路徑與檔名--->
                url管理器逐個匹配urlconf,記錄檢視函式
                ---檢視函式名--->
                檢視管理,找到對應的檢視去執行,返回結果給瀏覽器
                ---響應的資料--->
                返回第一步:使用者在瀏覽器中輸入網址
            網頁
                重定向
                錯誤檢視
                    404檢視:找不到網頁(url匹配不成功時返回)時返回
                        在templates目錄下定義404.html
                            <!doctype html>
                            <html lang="en">
                            <head>
                                <meta charset="UTF-8">
                                <meta name="viewport"
                                      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
                                <meta http-equiv="X-UA-Compatible" content="ie=edge">
                                <title>Document</title>
                            </head>
                            <body>
                                <h1>頁面丟失</h1>
                                <h2>{{request_path}}</h2>
                            </body>
                            </html>
                            request_path:導致錯誤的網址
                        配置settings.py
                            DEBUG
                                如果為 True,永遠不會呼叫404頁面,需要調整為 False 才會顯示
                            ALLOWED_HOSTS = ['*']
                    500檢視:在檢視程式碼中出現錯誤(伺服器程式碼錯誤)
                    400檢視:錯誤出現在客戶的操作
            JSON資料
    url配置
        配置流程:
            制定根級url配置檔案
                settings.py檔案中的ROOT_URLCONF
                ROOT_URLCONF = 'project.urls'
                預設實現了
            urlpatterns
                一個url例項的列表
                url物件
                    正則表示式
                    檢視名稱
                    名稱
            url匹配正則的注意事項
                如果想要從url中獲取一個值,需要對正則加小括號
                匹配正則前方不需要加'/'
                正則前需要加'r'表示字串不轉義
        引入其他url配置
            在應用中建立urls.py檔案,定義本應用的url配置,在工程urls.py中使用include方法
                project\urls.py
                from django.contrib import admin
                from django.conf.urls import url,include
                urlpatterns = [
                    url(r'^admin/', admin.site.urls),
                    url(r'^', include('myApp.urls', namespace="myAPP")),
                ]
                myApp\urls.py
                from django.urls import path, include
                from django.conf.urls import url
                from . import views
                urlpatterns = [
                    url(r'^$', views.index, name="index"),
                ]
        url的反向解析
            概述:如果在檢視,模板中使用了硬編碼連結,在url配置發生改變時,動態生成連結的地址
            解決:在使用連結時,通過url配置的名稱,動態生成url地址
            作用:使用url模板
    檢視函式
        定義檢視:
            本質:一個函式
            檢視引數:
                一個HttpRequest的例項
                通過正則表示式獲取的引數
            位置:一般在views.py檔案下定義
    HttpRequest物件
        概述:
            伺服器接收http請求後,會根據報文建立HttpRequest物件
            檢視的第一個引數就是HttpRequest物件
            django建立的,之後呼叫檢視時傳遞給檢視
        屬性
            path:請求的完整路徑(不包括域名和埠)
            method:表示請求的方式,常用的有GET,POST
            encoding:表示瀏覽器提交的資料的編碼方式,一般為utf-8
            GET:類似於字典的物件,包含了get請求的所有引數
            POST:類似於字典的物件,包含了post請求的所有引數
            FILES:類似字典的物件,包含了所有上傳的檔案
            COOKIES:字典,包含所有的cookie
            session:類似字典的物件,表示當前會話
        方法
            is_ajax():如果是通過XMLHttpRequest發起的,返回 True
        QueryDict物件
            request物件中的GET,POST都屬於QueryDict物件
            方法:
                get():
                    根據鍵獲取值,只能獲取一個值
                    www.sunck.wang/abc?a=1&b=2&c=3
                getlist()
                    將鍵的值以列表的形式返回
                    可以獲取多個值
                    www.sunck.wang/abc?a=1&b=2&c=3
        GET屬性
            獲取瀏覽器傳遞過來資料
            www.sunck.wang/abc?a=1&b=2&c=3
            urls.py
            url(r'^get1', views.get1),   #結尾不能加$,否則無法匹配
            views.py
            def get1(request):
                a = request.GET.get('a')
                b = request.GET.get('b')
                c = request.GET.get('c')
                return HttpResponse(a + " " + b + " " + c)

            www.sunck.wang/abc?a=1&a=2&c=3
            urls.py
            url(r'^get2', views.get2),
            views.py
            def get2(request):
                a = request.GET.getlist('a')
                a1 = a[0]
                a2 = a[1]
                c = request.GET.get('c')
                return HttpResponse(a1 + " " + a2 + " " + c)
        POST屬性
            使用表單模擬POST請求
            關閉CSRF:project\project\settings.py
                MIDDLEWARE = [
                    'django.middleware.security.SecurityMiddleware',
                    'django.contrib.sessions.middleware.SessionMiddleware',
                    'django.middleware.common.CommonMiddleware',
                    # 'django.middleware.csrf.CsrfViewMiddleware',
                    'django.contrib.auth.middleware.AuthenticationMiddleware',
                    'django.contrib.messages.middleware.MessageMiddleware',
                    'django.middleware.clickjacking.XFrameOptionsMiddleware',
                ]
            示例:
                def showregist(request):
                    return render(request, 'myApp/regist.html',)

                def regist(request):
                    name = request.POST.get("name")
                    gender = request.POST.get("gender")
                    age = request.POST.get("age")
                    hobby = request.POST.getlist("hobby")
                    print(name)
                    print(gender)
                    print(age)
                    print(hobby)
                    return HttpResponse("regist")
            路徑:
                url(r'^showregist/$', views.showregist),
                    url(r'^showregist/regist/$', views.regist),
            頁面:
                   <!doctype html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <meta name="viewport"
                          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
                    <meta http-equiv="X-UA-Compatible" content="ie=edge">
                    <title>註冊</title>
                </head>
                <body>
                    <form action="regist/" method="post">
                        姓名:<input type="text" name="name" value=""/>
                        <hr>
                        性別:<input type="radio" name="gender" value="1">男<input type="radio" name="gender" value="0">女
                        <hr>
                        愛好:<input type="checkbox" name="hobby" value="power"/>權利<input type="checkbox" name="hobby" value="money">金錢<input type="checkbox" name="hobby" value="beauty">美女<input type="checkbox" name="hobby" value="Tesla">Tesla
                        <hr>
                        <input type="submit" value="註冊">
                    </form>
                </body>
                </html>
    HttpResponse物件
        概述:
            作用:給瀏覽器返回資料
            HttpRequest物件是由Django建立的,HttpResponse物件是由程式設計師建立
        用法:
            不用模板,直接返回資料
                語句示例:return HttpResponse("Sunck is a good man")
            呼叫模板
                使用render方法
                    原型:render(request, templateName[, context])
                    作用:結合資料和模板,返回一個完整的HTML頁面
                    引數:
                        request:請求體物件
                        templateName:模板路徑
                        context:傳遞給需要渲染在模板上的資料
        屬性
            content:表示返回內容
            charset:編碼格式
            status_code:響應狀態碼
                200
                304
                404
                400
            content-type:指定輸出的MIME型別
        方法
            init:使用頁面內容例項化HttpResponse物件
            write(content):以檔案的形式寫入
            flush():以檔案的形式輸出緩衝區
            set_cookie(key, value, maxAge=None, exprise=None)
            delete_cookie(key):
                刪除cookie
                如果刪除一個不存在的cookie,就當什麼都沒發生
        子類HttpResponseRedirect
            功能:重定向,伺服器端的跳轉
            簡寫
                redirect(to)
            to推薦使用反向解析
            示例:
                from django.http import HttpResponseRedirect
                from django.shortcuts import redirect
                def redirect1(request):
                    # return HttpResponseRedirect('/redirect2')
                    return redirect('/redirect2')
                def redirect2(request):
                    return HttpResponse("我是重定向後的檢視")
        子類JsonResponse
            返回Json資料,一般用於非同步請求
            __init__(self.data)
            data 字典
            注意:Content-type型別為application/json
    狀態保持
        http協議是無狀態的,每次請求都是一次新的請求,它不記得之前的請求。
        客戶端與伺服器的一次通訊就是一次會話
        實現狀態的保持,在客戶端或服務端儲存有關會話的資料
        儲存的方式
            cookie:所有資料儲存在客戶端,不要儲存敏感的資料
            session:所有的資料儲存在服務端,在客戶端用cookie儲存session_id
        狀態保持的目的:
            在一段時間內跟蹤請求者的狀態,可以實現跨頁面訪問當前的請求者的資料
        注意:不同的請求者之間不會共享這個資料,與請求者一一對應
        啟用session:project\project\settings.py
            INSTALLED_APPS    'django.contrib.sessions',
            MIDDLEWARE    'django.contrib.sessions.middleware.SessionMiddleware',
        使用session
            啟用session後,每個httpRequest物件都有一個session屬性
            get[key, default=None]    根據鍵獲取session值
            clear()    清空所有會話
            flush()    刪除當前會話並刪除會話的cookie
            示例:
                # session
                def main(request):
                    # 取session
                    username = request.session.get('name', '遊客')
                    print(username)
                    return render(request, 'myApp/main.html', {'username': username})

                def login(request):
                    return render(request, 'myApp/login.html')

                def showmain(request):
                    print("*****************")
                    username = request.POST.get('username')
                    # 儲存session
                    request.session['name'] = username
                    return redirect('/main/')

                from django.contrib.auth import logout
                def quit(request):
                    # 清除session
                    logout(request) # 方法1,推薦
                    # request.session.clear() # 方法2
                    request.session.flush() # 方法3
                    return redirect('/main/')
        設定session過期時間
            set_expiry(value)
            request.session.set_expiry(10)  設定為10秒後過期
            如果不設定,2個星期後過期
            value設定為0代表關閉瀏覽器時過期
            value設定為None代表設定永不過期,不推薦



Redis使用:略

************************************************************************************************************
****************************************第二篇筆記從這裡開始************************************************
************************************************************************************************************

模板
    定義模板
        變數
            變數傳遞給模板的資料
            要遵守識別符號規則
            語法 {{ var }}
            注意:如果使用的變數不存在,則插入的是空字串
            在模板中使用點語法
                字典查詢
                屬性或者方法
                數字索引
            在模板中呼叫物件的方法
                注意:在模板裡定義的函式不能傳遞self以外的引數
        標籤:語法   {% tag %}
            作用
                在輸出中建立文字
                控制邏輯和迴圈
        標籤示例:    
            if 格式 
                    {% if 表示式 %}
                        語句
                    {% endif %}
            if-else 格式   
                        {% if 表示式 %}
                            語句1
                        {% else %}
                            語句else
                        {% endif %}
            if-elif-else 格式 
                        {% if 表示式 %}
                            語句1
                        {% elif 表示式 %}
                            語句2
                        ...

                        {% else %}
                            語句else
                        {% endif %}
            for 格式
                    {% for 變數 in 列表 %}
                        語句
                    {% endfor %}
                格式2
                    {% for 變數 in 列表 %}
                        語句
                    {% empty %}  # 注意:列表為空或者列表不存在時執行語句2
                        語句2
                    {% endfor %}
                格式3
                    {{ forloop.counter }}
                示例:
                    <ul>
                        {% for stu in students %}
                            <li>
                                {{forloop.counter}}--{{stu.sname}}--{{stu.sgrade}}
                            </li>
                        {% empty %}
                            <li>目前沒有學生</li>
                        {% endfor %}
            commnet 格式
                {% commnet %}
                    被註釋的內容
                {% endcomment %}
                作用:相當於多行註釋,被註釋的內容不再執行
            ifequal/ifnotequal 作用 判斷是否相等或者不相等
                格式
                    {% ifequal 值1 值2 %}
                        語句1
                    {% endifequal %}  # 如果值1等於值2,執行語句1,否則不執行語句1
            include
                作用:載入模板並以標籤內的引數渲染
                格式:{% include '模板目錄' 引數1 引數2 %}
            url
                作用:反射解析
                格式:{% url 'namespace: name' p1 p2 %}
            csrf_token
                作用:用於跨站請求偽造保護
                格式:{% csrf_token %}
            block, extends
                作用:用於模板的繼承
            autoescape
                作用:用於HTML轉義
        過濾器
            語法 {{ var|過濾器 }}
            作用:在變數被顯示前修改它,只是加一個效果,對變數不會造成影響
            示例:
                lower
                upper
            過濾器可以傳遞引數,引數用引號引起來
                join 格式 列表|join:"#"
                     示例:{{list1|join:"#"}}
            如果一個變數沒有被提供,或者值為false,空,我們可以通過 default 語法使用預設值
                格式: {{str1|default:"沒有"}}
            根據給定格式轉換日期為字串:date
                格式: {{dateVal|date:'y-m-d'}}
            HTML轉義:escape
            加減乘除示例:
                <h1>num = {{num|add:10}}</h1>
                <h1>num = {{num|add:-10}}</h1>
                <h1>num = {% num widthratio num 1 5%}</h1>
                <h1>num = {% num widthratio num 5 1%}</h1>
        註釋
            單行註釋:語法: {# 被註釋的內容 #}
            多行註釋
                {% commnet %}
                    被註釋的內容
                {% endcomment %}

    反射解析
        示例:
            project/project/urls.py
            url(r'^', include('myApp.urls', namespace='app')),
            project/myApp/urls.py
            url(r'^good/(\d+)$', views.good, name="good")
            templates/good.html
            <a href={% url 'app:good' 1 %}>連結</a>

    模板繼承
        作用:模板繼承可以減少頁面的重複定義,實現頁面的重用
        block標籤:在父模板中預留區域 ,子模板去填充
            語法 : {% block 標籤名 %}

                    {% endblock 標籤名 %}
        extends標籤:繼承模板,需要寫在模板檔案的第一行
            語法 : {% extends 'myApp/base.html' %}
                    {% block main %}
                        內容
                    {% endblock 標籤名 %}
        示例:
            定義父模板
                body標籤中
                {% block main %}
                        
                {% endblock main %}

                {% block main %}
                        
                {% endblock main2 %}
            定義子模板
                {% extends 'myApp/base.html' %}
                {% block main %}
                    <h1>sunck is a good man</h1>
                {% endblock main %}

                {% block main2 %}
                    <h1>kaige is a good man</h1>
                {% endblock main2 %}

    HTML轉義
        問題:return render(request, 'myApp/index.html', {"code": "<h1>sunck is a very good man</h1>"})中的{{code}}
              {{code}}裡的code被當作<h1>sunck is a very good man</h1>顯示,未經過渲染
        解決方法:
            {{code|safe}}
        或  {% autoescape off %}
                {{code}}
            {% endautoescape %}  # 這個可以一口氣解決一堆

    CSRF:
    跨站請求偽造
        某些惡意網站包含連結,表單,按鈕,js,利用登入使用者在瀏覽器中認證,從而攻擊服務
    防止CSRF
        在settings.py檔案的MIDDLEWARE增加'django.middleware.csrf.CsrfViewMiddleware'
        {% csrf_token %}        

    驗證碼
        作用
            在使用者註冊,登入頁面的時候使用,為了防止暴力請求,減輕伺服器的壓力
            是防止CSRF的一種方式

    驗證碼程式碼示例:
寫在views.py裡面
=================================================================================================
def verifycode(request):
    # 引入繪圖模組
    from PIL import Image, ImageDraw, ImageFont
    # 引入隨機函式模組
    import random
    # 定義變數,用於畫面的背景色,寬,高
    bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100))
    width = 100
    height = 50
    # 建立畫面物件
    im = Image.new('RGB', (width, height), bgcolor)
    # 建立畫面物件
    draw = ImageDraw.Draw(im)
    # 呼叫畫筆的point()函式繪製噪點
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    # 定義驗證碼的備選值
    str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
    # 隨機選取4個值作為驗證碼
    rand_str = ''
    for i in range(0, 4):
        rand_str += str[random.randrange(0, len(str))]
    # 構造字型物件
    font = ImageFont.truetype(r'C:\Windows\Fonts\AdobeArabic-Bold.otf', 40)
    # 構造字型顏色
    fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
    # 繪製4個字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
    # 釋放畫筆 
    del draw
    # 存入session,用於做進一步的驗證
    request.session['verifycode'] = rand_str
    # 記憶體檔案操作
    import io
    buf = io.BytesIO()
    # 將圖片儲存在記憶體中,檔案型別為png
    im.save(buf, 'png')
    # 將記憶體中的圖片資料返回給客戶端,MIME型別為圖片png
    return HttpResponse(buf.getvalue(), 'image/png')


from django.shortcuts import render, redirect
def verifycodefile(request):
    f = request.session["falg"]
    str = ""
    if f == False:
        str = "請重新輸入!"
    request.session.clear()
    return render(request, 'myApp/verifycodefile.html', {"flag":str})

def verifycodecheck(request):
    code1 = request.POST.get("verifycode").upper()
    code2 = request.session["verify"].upper()
    if code1 == code2:
        return render(request, 'myApp/success.html')
    else:
        request.session["flag"] = False
        return redirect('/verifycodefile')

==============================================================================
寫在verifycodefile.html的<body>標籤中
<body>
    <form method="post" action="/verifycodecheck/">
        {%csrf_token%}
        <input type="text" name="verifycode"/>
        <img src="/verifycode">
        <input type="submit" name="登入">
        <span>{{flag}}</span>
    </form>
</body>

==============================================================================


Django高階擴充套件
    靜態檔案
        css,js,圖片,json檔案,字型檔案等
        配置settings.py
            STATIC_URL = '/static'
            STATICFILES_DIRS = [
                os.path.join(BASE_DIR, 'static')
            ]

    中介軟體
        概述:一個輕量級,底層的外掛,可以介入Django的請求和響應。
        本質:一個Python類
        方法:
            __init__ 
                不需要傳引數,伺服器響應第一個請求的時候自動呼叫,用於確定是否啟用該中介軟體
            process_request(self, request) 
                在執行檢視之前被呼叫(分配url匹配檢視之前),每個請求都會呼叫,返回None或者HttpResponse物件
            process_view(self, request, view_func. view_args, view_kwargs)
                呼叫檢視之前執行,每個請求都會呼叫,返回None或者HttpResponse物件
            process_template_response(self, request, response)
                在檢視剛好執行完後呼叫,每個請求都會呼叫,返回None或者HttpResponse物件
                使用render
            process_response(self, request, response)
                所有響應返回瀏覽器之前呼叫,每個請求都會呼叫,返回HttpResponse物件
            process_exception(self, request, exception)
                當檢視丟擲異常時呼叫,返回HttpResponse物件
        執行過程:
            __init__ --> process_request--> url --> process_view --> view --> process_template_response --> template --> process_response -->返回開頭部分
         執行位置:
        自定義中介軟體
            在工程目錄下的middleware目錄下建立myApp
            建立一個python檔案
            from django.utils.deprecation import middlewareMixin
            class MyMiddle(middlewareMixin):
                def process_request(self, request):
                    print("get引數為: ", request.GET.get("a"))
        使用自定義中介軟體
            配置settings.py檔案 在MIDDLEWARE中新增 'middleware.myApp.MyMiddle.MyMiddle',

    上傳圖片
        概述:
            檔案上傳時,檔案資料request.FILES屬性中.
            注意:form表單要上傳檔案需要加enctype="multipart/form-data"
            注意:上傳檔案必須用post請求
        儲存路徑:
            在static目錄下建立upfile目錄用於儲存上傳的檔案
            配置settings.py檔案 MDEIA_ROOT = os.path.join(BASE_DIR, r'static\upfile')

views.py內容
==============================================================================
def upfile(request):
    return render(request, 'myApp/upfile.html')

import os
from django.conf import settings
def savefile(request):
    if request.method == "POST":
        f = request.FILES["file"]
        # 檔案在伺服器端的路徑
        filePath = os.pasth.join(settings.MDEIA_ROOT, f.name)
        with open(filePath, 'wb') as fp:
            for info in f.chunks():
                fp.write(info)
        return HttpResponse("上傳成功。")
    else:
        return HttpResponse("上傳失敗。")
==============================================================================
upfile.html中<body>裡的內容
<body>
    <form method="post" action="/savefile" enctype="multipart/form-data">
        {%csrf_token%}
        <input type="file" name="file"/>
        <input type="submit" value="上傳"/>
    </form>
</body>
==============================================================================

    分頁
        Paginator物件
            建立物件
                格式 Paginator(列表,整數)
                返回值 返回的分頁物件
            屬性
                count 物件總數
                num_pages 頁面總數
                page_range
                    頁碼列表
                    [1,2,3,4,5]
                    頁碼從1開始
            方法
                page(num) 獲得一個Page物件,如果提供的頁碼不存在會丟擲"InvalidPage"異常
            異常
                InvalidPage:當向 page()傳遞的是一個無效的頁碼時丟擲
                PageNotAnInteger:當向 page()傳遞的不是一個整數時丟擲
                EmptyPage:當向 page()傳遞一個有效值,但是該頁面裡沒有資料時丟擲
        Page物件
            建立物件
                Paginator物件的 page()方法返回得到Page物件
                不需要手動建立
            屬性
                object_list:當前頁上所有資料(物件)列表
                number:當前頁面的頁碼值
                paginator:當前page物件關聯的paginator物件
            方法
                has_next() 判斷是否有下一頁,如果有返回 True
                has_previous() 判斷是否有上一頁,如果有返回 True
                has_other_pages() 判斷是否有上一頁或者下一頁,如果有返回 True
                next_page_number() 返回下一頁的頁碼,如果下一頁不存在丟擲InvalidPage異常
                previous_page_number() 返回上一頁的頁碼,如果上一頁不存在,丟擲InvalidPage異常
                len() 返回當前頁的資料(物件)個數

        Paginator與Page物件關係(略)
        程式碼示例:
        配置路由:url(r'^studentpage/(\d+)/$', views.studentpage),
        配置檢視:
            from .models import Students
            from django.core.paginator import Paginator
            def studentpage(request, pageid):
                # 所有學生列表
                allList = Students.objects.all()
                paginator = Paginator(allList, 6)
                page = paginator.page(pageid)
                return render(request, 'myApp/studentpage.html', {"students": page})
        配置html
        studentpage.html中body標籤中的內容:
            <body>
                <ul>
                    {% for stu in students %}
                    <li>
                        {{stu.sname}}--{{stu.sgrade}}
                    </li>
                    {% endfor %}
                </ul>
                <ul>
                    {% for index in students.paginator.page_range %}
                        {% if index == students.number %}
                            <li>
                                {{index}}
                            </li>
                        {% else %}
                            <li>
                                <a href="/sunck/studentpage/{{index}}">{{index}}</a>
                            </li>
                        {% endif %}
                    {% endif%}
                </ul>
            </body>
==============================================================================

    ajax
        需要動態生成,請求JSON資料
    程式碼示例
        ajaxstudents.html頁面示例
        <script type="text/javascript" src="/static/myApp/js/jquery-3.1.1.min.js"></script>
        <body>
            <h1>學生資訊列表</h1>
            <button id="btn">顯示學生資訊</button>
            <script type="text/javascript" src="/static/myApp/js/sunck.js"></script>
        </body>

        sunck.js程式碼示例
        $(document).ready(function (){
            document.getElementById("btn").onclick = function (){
                $.ajax({
                    type:"get",
                    url:"/studentsinfo/",
                    dataType:"json",
                    success:function(data, status){
                        console.log(data)
                        var d = data["data"]
                        for(var i=0; i<d.length; i++){
                            document.writ