Django1


1. DJANGO使用指南



Django簡介:

Django官網(wǎng)地址

Django發(fā)布于2005年7月,是當前Python世界里最有名且成熟的網(wǎng)絡(luò)框架。 最初是被開發(fā)用于管理勞倫斯出版集團旗下的以新聞內(nèi)容為主的網(wǎng)站的,即CMS(內(nèi)容管理系統(tǒng))軟件。

Django是一個用Python編寫的開放源代碼的Web應用框架,代碼是開源的。此系統(tǒng)采用了MVC的框架模式, 也可以稱為MTV模式


什么是MVC模式

MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設(shè)計典范,用一種業(yè)務邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務邏輯聚集到一個部件里面,在改進和個性化定制界面及用戶交互的同時,不需要重新編寫業(yè)務邏輯。MVC被獨特的發(fā)展起來用于映射傳統(tǒng)的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結(jié)構(gòu)中。 <b>通俗的來講就是,強制性的使應用程序的輸入,處理和輸出分開。</b>

<b>核心思想</b>:解耦

<b>優(yōu)點</b>:減低各個模塊之間的耦合性,方便變更,更容易重構(gòu)代碼,最大程度的實現(xiàn)了代碼的重用

MVC(Model, View, Controller)
Model: 即<font color=red>數(shù)據(jù)存取層</font>。用于封裝于應用程序的業(yè)務邏輯相關(guān)的數(shù)據(jù),以及對數(shù)據(jù)的處理。說白了就是模型對象負責在數(shù)據(jù)庫中存取數(shù)據(jù)

View: 即<font color=red>表現(xiàn)層</font>。負責數(shù)據(jù)的顯示和呈現(xiàn)。渲染的html頁面給用戶,或者返回數(shù)據(jù)給用戶。

Controller: 即<font color=red>業(yè)務邏輯層</font>。負責從用戶端收集用戶的輸入,進行業(yè)務邏輯處理,包括向模型中發(fā)送數(shù)據(jù),進行CRUD操作。

圖解:


image.png

瀏覽器中MVC的表現(xiàn)形式圖解:


image.png


Django的模式簡介

MVT模式

嚴格來說,Django的模式應該是MVT模式,本質(zhì)上和MVC沒什么區(qū)別,也是各組件之間為了保持松耦合關(guān)系,只是定義上有些許不同。

Model: 負責業(yè)務與數(shù)據(jù)庫(ORM)的對象

View: 負責業(yè)務邏輯并適當調(diào)用Model和Template

Template: 負責把頁面渲染展示給用戶

注意: Django中還有一個url分發(fā)器,也叫作路由。主要用于將url請求發(fā)送給不同的View處理,View在進行相關(guān)的業(yè)務邏輯處理。


2. VIRTUALENV虛擬環(huán)境創(chuàng)建指南



前言
  1. 本教程中使用到的python版本均為python3.x版本,由于本人安裝的是python3.6.3版本,所以一下的課程均是在此基礎(chǔ)上進行的。
     

  2. virtualenv使用場景:當開發(fā)成員負責多個項目的時候,每個項目安裝的庫又是有很多差距的時候,會使用虛擬環(huán)境將每個項目的環(huán)境給隔離開來。
     

    比如,在有一個老項目已經(jīng)開發(fā)維護了3年了,里面很多庫都是比較老的版本了。例如python使用的是2.7版本的。但是新項目使用的python版本是3.6的。為了解決這種項目執(zhí)行環(huán)境的沖突,所以引入了虛擬環(huán)境virtualenv。

當然除了virtualenv可以起到隔離環(huán)境的作用,還有其他技術(shù)方案來實現(xiàn),而且上線流程簡單,大大減輕運維人員的出錯率,比如每一個項目使用一個docker鏡像,在鏡像中去安裝項目所需的環(huán)境,庫版本等等

python環(huán)境的配置

  1. 在cmd中能通過python去啟動,如果不行直接跳到第三步
image.png


  1. 在cmd中能通過pip3啟動安裝軟件,如果不行直接跳到第三步


    image.png


3.配置python環(huán)境和pip環(huán)境


image.png
  1. 確認pip安裝成功,如果Scritp文件夾下沒有pip可執(zhí)行文件,則執(zhí)行第五步。

  2. 由于python3.6安裝以后,在Scripts文件中沒有pip的可執(zhí)行軟件,需要輸入一下命令進行安裝

python -m ensurepip
image.png

注:現(xiàn)在在python的安裝文件夾Scripts下就有pip.exe以及easy_install.exe等可執(zhí)行文件了,就可以使用pip安裝啦~

windows中安裝使用

  1. 安裝virtualenv
pip install  virtualenv
image.png
  1. 創(chuàng)建虛擬環(huán)境

先查看一下安裝虛擬環(huán)境有那些參數(shù),是必須填寫的


image.png

注意兩個參數(shù):
--no-site-packages和-p參數(shù)


image.png
virtualenv --no-site-packages venv

以下是指定安裝虛擬環(huán)境中的python版本的安裝方式:


image.png


  1. 進入/退出env
進入 cd env/Scripts/文件夾  在activate命令

退出 deactivate

在pycharm中創(chuàng)建項目方法

image.png

ubuntu中安裝使用

  1. 安裝virtualenv
apt-get install python-virtualenv
  1. 創(chuàng)建包含python3版本的虛擬環(huán)境
virtualenv -p /usr/bin/python3 env

env代表創(chuàng)建的虛擬環(huán)境的名稱

  1. 進入/退出env
進入 source env/bin/activate

退出 deactivate
  1. pip使用

    查看虛擬環(huán)境下安裝的所有的包

    pip list
    

    查看虛擬環(huán)境重通過pip安裝的包

    pip freeze
    

3. DJANGO使用指南



創(chuàng)建Django項目

cmd命令創(chuàng)建步項目驟步驟:
1、進入創(chuàng)建好的虛擬環(huán)境
2、去到需要放置項目的文件夾下,新建項目
3、創(chuàng)建好項目后拖動到pycharm中打開

直接用pycharm創(chuàng)建項目步驟:


image.png
1. 首先創(chuàng)建一個運行Django項目的虛擬環(huán)境(virtualenv)

虛擬環(huán)境的創(chuàng)建在基礎(chǔ)課程中講解,地址
該虛擬環(huán)境中有django庫,python3,pymysql等等需要的庫

大致在羅列下安裝了那些庫:

pip install Django==1.11

pip install PyMySQL
2. 創(chuàng)建一個Django項目

2.1 創(chuàng)建項目

django-admin startproject halloWorld

該命令是創(chuàng)建一個名為halloWorld的工程

項目目錄介紹

下面展示創(chuàng)建以后的文件,具體有哪些文件:


image.png

manage.py: 是Django用于管理本項目的管理集工具,之后站點運行,數(shù)據(jù)庫自動生成,數(shù)據(jù)表的修改等都是通過該文件完成。

init.py: 指明該目錄結(jié)構(gòu)是一個python包,暫無內(nèi)容,在后期會初始化一些工具會使用到。

seetings.py: Django項目的配置文件,其中定義了本項目的引用組件,項目名,數(shù)據(jù)庫,靜態(tài)資源,調(diào)試模式,域名限制等

urls.py:項目的URL路由映射,實現(xiàn)客戶端請求url由哪個模塊進行響應。

wsgi.py:定義WSGI接口信息,通常本文件生成后無需改動

2.2 運行Django項目

python manage.py runserver 端口

該命令是運行項目,端口可以不用寫,啟動的時候會默認隨機創(chuàng)建一個可以使用的端口

2.2 創(chuàng)建app

python manage.py startapp hallo_app

該命令是在blog工程下創(chuàng)建一個名為hallo_app的app

3. settings.py配置文件詳細解讀
a) 設(shè)置語言:

LANGUAGE_CODE = 'zh-hans' 表示中文
LANGUAGE_CODE = 'en-us' 表示英文

image.png

設(shè)置時區(qū): TIME_ZONE = 'Asia/Shanghai'

b) 時區(qū)解釋: (需要詳細回顧思考時區(qū)問題)

UTC:世界標準時間,也就是平常說的零時區(qū)。
北京時間表示東八區(qū)時間,即UTC+8

模型使用指南--admin

前言

Djang自身集成了管理后臺,在管理后臺中可以對我們自定義model進行CRUD操作,也能進行列表展示解析,分頁等等

使用admin管理后臺

0. 準備工作,在model中定義Student的模型
```
class Students(models.Model):
    name = models.CharField(max_length=10)
    sex = models.BooleanField()

    class Meta:
        db_table = 'student'
```
1. admin管理后臺的url
在工程目錄下可以看到路由配置中有一個admin的url地址
```
url(r'^admin/', admin.site.urls),
```
2. 創(chuàng)建admin后臺的用戶密碼
```
python manage.py createsuperuser
```
[圖片上傳失敗...(image-4a4434-1536808795504)]
3. 在登錄后的管理后臺中對自定義的模型進行CRUD操作
在管理后臺中操作模型對象。需要在app的admin.py中寫如下代碼
```
admin.site.register(模型名)
```
4. 繼承admin.ModelAdmin,編寫自定義的admin
```
class StudentAdmin(admin.ModelAdmin):
    def set_sex(self):
        if self.sex:
            return '男'
        else:
            return '女'
    set_sex.short_description = '性別'
    list_display = ['id', 'name', set_sex]
    list_filter = ['sex']
    search_fields = ['name']
    list_per_page = 1

admin.site.register(模型名, StudentAdmin)
```

其中:<br>
list_display: 顯示字段  <br>
list_filter: 過濾字段   <br>
search_fields: 搜索字段 <br>
list_per_page: 分頁條數(shù) <br>
5. 使用裝飾器去實現(xiàn)注冊
```
@admin.register(模型名)
class StudentAdmin(admin.ModelAdmin):
    def set_sex(self):
        if self.sex:
            return '男'
        else:
            return '女'
    set_sex.short_description = '性別'
    list_display = ['id', 'name', set_sex]
    list_filter = ['sex']
    search_fields = ['name']
    list_per_page = 1
```

模型使用指南--models

前言

Django對數(shù)據(jù)庫提供了很好的支持,對不同的數(shù)據(jù)庫,django提供了統(tǒng)一調(diào)用的API,我們可以根據(jù)不同的業(yè)務需求使用不同是數(shù)據(jù)庫。Django中引入了ORM(Objects Relational Mapping)對象關(guān)系映射,是一種程序技術(shù)。在下面會詳細的講解。

修改mysql配置

1. 在settings.py中配置數(shù)據(jù)庫連接信息
'ENGINE':'django.db.backends.mysql',
'NAME':'',           #數(shù)據(jù)庫名
'USER':'',           #賬號
'PASSWORD':'',       #密碼
'HOST':'127.0.0.1',  #IP(本地地址也可以是localhost)
'PORT':'3306',       #端口
2. mysql數(shù)據(jù)庫中創(chuàng)建定義的數(shù)據(jù)庫

a) 進入mysql

mysql -u root -p

b) 創(chuàng)建數(shù)據(jù)庫

create database xxx charset=utf-8;
3. 配置數(shù)據(jù)庫鏈接

a) 安裝pymysql

pip install pymysql

b) 在工程目錄下的init.py文件中輸入,完成數(shù)據(jù)庫的驅(qū)動加載

import pymysql
pymysql.install_as_MySQLdb()
4. 定義模型,以及模型數(shù)據(jù)的增刪改查
重要概念:模型,表,屬性,字段

一個模型類在數(shù)據(jù)庫中對應一張表,在模型類中定義的屬性,對應模型對照表中的一個字段

定義屬性見定義屬性文件地址

創(chuàng)建學生模型類
class Student(models.Model):

    s_name = models.CharField(max_length=10)
    s_age = models.IntegerField()
    s_gender = models.BooleanField()

    class Meta:
        db_table = 'cd_student'
        ordering =[]
    對象的默認排序字段,獲取對象列表時使用,升序ordering['id'],降序ordering['-id']
5.遷移數(shù)據(jù)庫

a) 生成遷移文件

python manage.py makemigrations

遷移成功會在migrations文件夾下生成0001_initial.py

注意:如果執(zhí)行后并沒有生成遷移文件,一直提示No changes detected這個結(jié)果的話,就要手動的去處理了。有兩點處理方式:

1) 先刪除掉pycache文件夾

2) 直接強制的去執(zhí)行遷移命令,python manage.py makemigrations xxx (xxx就是app的名稱)

3) 查看自動生成的數(shù)據(jù)庫,查看表django_migrations,刪掉app字段為xxx的數(shù)據(jù)(xxx就是app的名稱)

b) 執(zhí)行遷移生成數(shù)據(jù)庫

python manage.py migrate

注意: 生成遷移文件的時候,并沒有在數(shù)據(jù)庫中生成對應的表,而是執(zhí)行migrate命令之后才會在數(shù)據(jù)庫中生成表

6. ORM

ORM(Objects Relational Mapping)對象關(guān)系映射,是一種程序技術(shù),用于實現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換??梢院唵卫斫鉃榉g機。

可以理解為把面向?qū)ο蟮拇a,翻譯成數(shù)據(jù)庫可以看懂的SQL語句

image.png
7.模型查詢
a) 模型成員objects

Django默認通過模型的objects對象實現(xiàn)模型數(shù)據(jù)查詢

b) 過濾器

查詢集表示從數(shù)據(jù)庫獲取的對象集合

查詢集可以有多個過濾器

過濾器就是一個函數(shù),基于所給的參數(shù)限制查詢的結(jié)果

從SQL角度來說,查詢集合和select語句等價,過濾器就像where條件

Django有兩種過濾器用于篩選記錄

    filter    : 返回符合篩選條件的數(shù)據(jù)集

    exclude   : 返回不符合篩選條件的數(shù)據(jù)集

多個filter和exclude可以連接在一起查詢

當然還有如下這些過濾器:

all()            返回所有數(shù)據(jù)

filter()     返回符合條件的數(shù)據(jù)(數(shù)據(jù)可以有一個或者多個),條件可以有多個
 例:類名.objects.filter(條件1,條件2...)

get()  返回符合條件的一條數(shù)據(jù),沒有數(shù)據(jù)會報錯,返回數(shù)據(jù)太多也報錯

exclude()        過濾掉符合條件的數(shù)據(jù)

order_by()       排序,
升序例:類名.objects.order_by(字段) 
降序例:類名.objects.order_by(-字段) 

values()         一條數(shù)據(jù)就是一個字典,返回一個列表
c) 查詢單個數(shù)據(jù)

get():返回一個滿足條件的對象。如果沒有返回符合條件的對象,會應該模型類DoesNotExist異常,如果找到多個,會引發(fā)模型類MultiObjectsReturned異常

first():返回查詢集中的第一個對象

last():返回查詢集中的最后一個對象

count():返回當前查詢集中的對象個數(shù)

exists():判斷查詢集中是否有數(shù)據(jù),如果有數(shù)據(jù)返回True,沒有返回False

d) 限制查詢集

限制查詢集,可以使用下表的方法進行限制,等同于sql中的limit

模型名.objects.all()[0:5] 下標不能為負數(shù);[:100]結(jié)束索引超出范圍不報錯;[100:]起始索引超出范圍也不報錯,返回空

e) 字段查詢

對sql中的where實現(xiàn),作為方法,filter(),exclude(),get()的參數(shù)

語法:屬性名稱__比較運算符 = 值

外鍵:屬性名_id

注意:like語句中使用%表示通配符。比如sql語句查詢 where name like '%xxx%',等同于filter(name_contains='xxx')

f) 比較運算符

contains:是否包含,大小寫敏感
例:模型名.objects.filter(字段名__contains='花'):模糊查詢名字中帶有‘花’的名字

startswith,endswith:以values開頭或者結(jié)尾,大小寫敏感
以上的運算符前加上i(ignore)就不區(qū)分大小寫了
例:模型名.objects.filter(字段名__startswith='花'):模糊查詢名字以‘花’開頭的名字

isnull,isnotnull:是否為空。
例:filter(name__isnull=True) :查詢名字為空的學生

in:是否包含在范圍內(nèi)。
例:filter(id__in=[1,2,3]) :查詢id在123的

gt,gte,lt,lte:大于,大于等于,小于,小于等于。
例:filter(age__gt=10) :查詢年齡大于10

pk:代表主鍵,也就是id。
例:filter(pk=1) :查詢id為1的

g) 聚合函數(shù)

aggregate()函數(shù)返回聚合函數(shù)的值

Avg:平均值

Count:數(shù)量

Max:最大

Min:最小

Sum:求和

例如: Student.objects.aggregate(Max('age'))

h) F對象/Q對象
<b>F對象:</b>可以使用模型的A屬性與B屬性進行比較

背景:在模型中有兩個字段,分別表示學生成績A與成績B,要對成績AB進行比較計算,就需要使用到F對象。

例如有如下例子1:

班級中有女生個數(shù)字段以及男生個數(shù)字段,統(tǒng)計女生數(shù)大于男生數(shù)的班級可以如下操作:

grades = Grade.objects.filter(girlnum__gt=F('boynum'))

F對象支持算數(shù)運算

grades = Grade.objects.filter(girlnum__gt=F('boynum') + 10)

例子2:

查詢python班下語文成績超過數(shù)學成績10分的學生

    grade = Grade.objects.filter(g_name='python').first()
    students = grade.student_set.all()

    stu = students.filter(s_yuwen__gt= F('s_shuxue') + 10)
<b>Q對象:</b>Q()對象就是為了將過濾條件組合起來

當我們在查詢的條件中需要組合條件時(例如兩個條件“且”或者“或”)時。我們可以使用Q()查詢對象

使用符號&或者|將多個Q()對象組合起來傳遞給filter(),exclude(),get()等函數(shù)

Q()對象的前面使用字符“~”來代表意義“非”

例子1:

查詢學生中不是12歲的或者姓名叫張三的學生

student = Student.objects.filter(~Q(age=12) | Q(name='張三'))

例子2:

查詢python班語文小于80并且數(shù)學小于等于80的學生

grade = Grade.objects.filter(g_name='python').first()
students = grade.student_set.all()
stu = students.filter(~Q(s_yuwen__gte=80) & Q(s_shuxue__lte=80))

例子3:

查詢python班語文大于等于80或者數(shù)學小于等于80的學生

grade = Grade.objects.filter(g_name='python').first()
students = grade.student_set.all()

stu = students.filter(Q(s_yuwen__gte=80) | Q(s_shuxue__lte=80))
delete刪除字段

例:模型名.objects.filter(s_name='小草').filter().delete() :將第一個名字為小草的人刪除

update更新數(shù)據(jù)

例:模型名.objects.filter(id=1).update(s_name='大大'):將id為1的名字改為‘大大’

8.模型字段定義屬性

定義屬性

概述
    ·django根據(jù)屬性的類型確定以下信息
        ·當前選擇的數(shù)據(jù)庫支持字段的類型
        ·渲染管理表單時使用的默認html控件
        ·在管理站點最低限度的驗證

    ·django會為表增加自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設(shè)置某屬性為主鍵列后,則django不會再生成默認的主鍵列

    ·屬性命名限制
        ·遵循標識符規(guī)則(不使用python預定義的標識符號,內(nèi)置函數(shù)名,異常等。避免使用下劃線等)
        ·由于django的查詢方式,不允許使用連續(xù)的下劃線



庫
    ·定義屬性時,需要字段類型,字段類型被定義在django.db.models.fields目錄下,為了方便使用,被導入到django.db.models中

    ·使用方式
        ·導入from django.db import models
        ·通過models.Field創(chuàng)建字段類型的對象,賦值給屬性


邏輯刪除
    ·對于重要數(shù)據(jù)都做邏輯刪除,不做物理刪除,實現(xiàn)方法是定義isDelete屬性,類型為BooleanField,默認值為False


字段類型
    ·AutoField
        ·一個根據(jù)實際ID自動增長的IntegerField,通常不指定如果不指定,一個主鍵字段將自動添加到模型中

    ·CharField(max_length=字符長度)
        ·字符串,默認的表單樣式是 TextInput

    ·TextField
        ·大文本字段,一般超過4000使用,默認的表單控件是Textarea

    ·IntegerField
        ·整數(shù)

    ·DecimalField(max_digits=None, decimal_places=None)
        ·使用python的Decimal實例表示的十進制浮點數(shù)
        ·參數(shù)說明
            ·DecimalField.max_digits
                ·位數(shù)總數(shù)
            ·DecimalField.decimal_places
                ·小數(shù)點后的數(shù)字位數(shù)

    ·FloatField
        ·用Python的float實例來表示的浮點數(shù)

    ·BooleanField
        ·true/false 字段,此字段的默認表單控制是CheckboxInput

    ·NullBooleanField
        ·支持null、true、false三種值

    ·DateField([auto_now=False, auto_now_add=False])
        ·使用Python的datetime.date實例表示的日期
        ·參數(shù)說明
            ·DateField.auto_now
                ·每次保存對象時,自動設(shè)置該字段為當前時間,用于"最后一次修改"的時間戳,它總是使用當前日期,默認為false
            ·DateField.auto_now_add
                ·當對象第一次被創(chuàng)建時自動設(shè)置當前時間,用于創(chuàng)建的時間戳,它總是使用當前日期,默認為false
        ·說明
            ·該字段默認對應的表單控件是一個TextInput. 在管理員站點添加了一個JavaScript寫的日歷控件,和一個“Today"的快捷按鈕,包含了一個額外的invalid_date錯誤消息鍵
        ·注意
            ·auto_now_add, auto_now, and default 這些設(shè)置是相互排斥的,他們之間的任何組合將會發(fā)生錯誤的結(jié)果

    ·TimeField
        ·使用Python的datetime.time實例表示的時間,參數(shù)同DateField

    ·DateTimeField
        ·使用Python的datetime.datetime實例表示的日期和時間,參數(shù)同DateField

    ·FileField
        ·一個上傳文件的字段

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


字段選項
    ·概述
        ·通過字段選項,可以實現(xiàn)對字段的約束
        ·在字段對象時通過關(guān)鍵字參數(shù)指定

    ·null
        ·如果為True,則該字段在數(shù)據(jù)庫中是空數(shù)據(jù),默認值是 False

    ·blank
        ·如果為True,則該字段允許為空白,默認值是 False

    ·注意
        ·null是數(shù)據(jù)庫范疇的概念,blank是表單驗證證范疇的

    ·db_column
        ·字段的名稱,如果未指定,則使用屬性的名稱

    ·db_index
        ·若值為 True, 則在表中會為此字段創(chuàng)建索引

    ·default
        ·默認值

    ·primary_key
        ·若為 True, 則該字段會成為模型的主鍵字段

    ·unique
        ·如果為 True, 這個字段在表中必須有唯一值

模型練習指南

前言

通過講mysql的系統(tǒng),翻譯一遍,在django中通過創(chuàng)建model去和數(shù)據(jù)庫中的表進行一一映射,并且通過ORM封裝
的處理方式去練習這一到習題,并寫出如下的解題答案

1.數(shù)據(jù)庫準備

在model中定義數(shù)據(jù)庫,其中的性別,男的存1,女的存0。
```
class Student(models.Model):
stuname = models.CharField(max_length=20)
studex = models.BooleanField()
stubirth = models.DateField()
stutel = models.CharField(max_length=255)

    class Meta:
        db_table = 'student'
```

2.數(shù)據(jù)庫遷移

python manage.py makemigrations
python manage.py migrate

3. 數(shù)據(jù)插入

3.1 使用表單form提交post請求數(shù)據(jù)
<form action="/app/addStu/" method="post">
    stuname: <input type="text" name="name">
    stusex: <input type="text" name="sex">
    stubirth: <input type="date" name="birth">
    stutel: <input type="text" name="tel">
    <input type="submit" value="提交">
</form>
3.2 獲取post請求,獲取請求數(shù)據(jù),并且創(chuàng)建數(shù)據(jù)
    stu = Student()
    stu.stuname = stuname
    stu.stusex = sex
    stu.stubirth = birth
    stu.stutel = tel
    stu.save()

    方法2:
    Student.objects.create(stuname=stuname, stusex=sex, stubirth=birth, stutel=tel)

4. 查詢所有的學生信息

使用all()方法獲取所有的數(shù)據(jù)

Student.objects.all()

4. 查詢所有女學生的姓名和出生日期

Student.objects.filter(stusex=0)
或者
Student.objects.exclude(stusex=1)

其中:
filter():返回符合條件的數(shù)據(jù)
exclude():過濾掉符合條件的數(shù)據(jù)

5.查詢所有的學生,按照id從大到小排序

Student.objects.all().order_by('-id')

其中:
order_by('id'):表示按照id升序的排列
order_by('-id'):表示按照id降序的排列

6. 查詢單個數(shù)據(jù),就不做演示了,可以使用一下的方法去獲取

get():返回一個滿足條件的對象。如果沒有返回符合條件的對象,會應該模型類DoesNotExist異常,如果找到多個,會引發(fā)模型類MultiObjectsReturned異常

first():返回查詢集中的第一個對象

last():返回查詢集中的最后一個對象

count():返回當前查詢集中的對象個數(shù)

exists():判斷查詢集中是否有數(shù)據(jù),如果有數(shù)據(jù)返回True,沒有返回False

7.查詢所有80后學生的姓名、性別和出生日期(篩選)

Student.objects.filter(stubirth__gte='1980-01-01', stubirth__lte='1990-01-01')

8.查詢名字中有王字的學生的姓名(模糊)

Student.objects.filter(stuname__contains='王')

9.查詢姓王的學生姓名和性別(模糊)

Student.objects.filter(stuname__startswith='王')

思考:以什么結(jié)束應該怎么寫----》 使用endswith

模型加餐使用指南

前言

該文檔中主要介紹模型的對應關(guān)系,一對一,一對多,以及多對多的關(guān)系。并且舉例說明
模型對應關(guān)系描述如下:
1:1 一對一 OneToOneField :關(guān)聯(lián)代碼兩個模型都可以寫

1:N   一對多 ForeignKey :關(guān)聯(lián)代碼必須寫到多的模型中(如:一個班級有多個學生,那么關(guān)聯(lián)代碼必須寫到班級模型中)

M:N   多對多 ManyToManyField:關(guān)聯(lián)代碼兩個模型都可以寫,多對多遷移后django會自動創(chuàng)建好中間表;add添加;remove刪除

常見的幾種數(shù)據(jù)關(guān)系,django都提供了很好的支持

1. 一對一

1.1 模型
    創(chuàng)建學生的模型:
    class Student(models.Model):
        stu_name = models.CharField(max_length=6, unique=True)
        stu_sex = models.BooleanField(default=0)
        stu_birth = models.DateField()
        stu_delete = models.BooleanField(default=0)
        stu_create_time = models.DateField(auto_now_add=True)
        stu_operate_time = models.DateField(auto_now=True)
        stu_tel = models.CharField(max_length=11)
        stu_yuwen = models.DecimalField(max_digits=3, decimal_places=1, default=0)
        stu_shuxue = models.DecimalField(max_digits=3, decimal_places=1, default=0)

        class Meta:
            db_table = 'stu'

    創(chuàng)建學生拓展的模型:
    class StuInfo(models.Model):

        stu_addr = models.CharField(max_length=30)
        stu_age = models.IntegerField()
        stu = models.OneToOneField(Student)

        class Meta:
            db_table = 'stu_info'
使用models.OneToOneField()進行關(guān)聯(lián)
class StuInfo(models.Model):下是通過班級獲取學生信
    stu = models.OneToOneField(Student)
注意:在數(shù)據(jù)中關(guān)聯(lián)字段名稱叫stu_id
1.2 通過學生拓展表去獲取學生信息
```
    stuinfo = StuInfo.objects.all().first()
    student = stuinfo.stu
```
注意:通過拓展表去獲取學生的信息的話,語法如下;
    學生拓展表的單條對象.關(guān)聯(lián)字段,即可獲取到學生表的數(shù)據(jù)
1.3 通過學生獲取人信息1
```
    stu = Student.objects.all().first()
    stuInfo = stu.stuinfo
```
注意:通過學生獲取關(guān)聯(lián)表的數(shù)據(jù)的話,語法如下:
    學生對象.關(guān)聯(lián)的表名,即可獲取到關(guān)聯(lián)表的數(shù)據(jù)
1.3.1 通過學生獲取人信息2
在關(guān)聯(lián)字段OneToOneField中加入?yún)?shù)related_name='xxx'
```
    在
    stu = Student.objects.all().first()
    stuInfo = stu.xxx
```
注意:通過學生獲取關(guān)聯(lián)表的數(shù)據(jù)的話,語法如下:
    學生對象.關(guān)聯(lián)的字段中定義的related_name參數(shù),即可獲取到關(guān)聯(lián)表的數(shù)據(jù)
1.4 設(shè)置對應關(guān)系的字段為保護模式 :
models.CASCADE                      默認值
models.PROTECT                  保護模式
models.SET_NULL                 置空模式
models.SET_DETAULT          置默認值
models.SET()     刪除的時候吃重新動態(tài)指向一個實體訪問對象元素
on_delete = models.PROTECT

```
修改on_delete參數(shù)
models.OneToOneField('Student', on_delete=models.SET_NULL, null=True)
```
在刪除student對象的時候,stuinfo的關(guān)聯(lián)字段會設(shè)置為空null=True,如下命令去刪除student的數(shù)據(jù):
```
Student.objects.filter(id=1).delete()
```
1.5 定義on_delete=models.PROTECT
p =  Student.objects.all().first()
p.delete()

注意:這個時候去執(zhí)行該業(yè)務邏輯的方法的時候會報錯

image.png

2. 一對多

2.1 模型
```
    定義一個班級類還有學生類,實現(xiàn)一對多的關(guān)系:
    先定義班級類
    Class Grade(models.Model):
        g_name = models.CharField(max_length=16)

    定義student
        class Student:
            s_name = models.CharField(max_length=10)
            s_age = models.IntegerField(default=1)
            s_grade = models.ForeignKey(Grade, on_delete=PROTECT)
```

注意:使用models.ForeignKey關(guān)聯(lián)
獲取對象元素 grade.student_set

2.2 獲取數(shù)據(jù)

語法:通過一獲取多的數(shù)據(jù)

公式: <b>一的對象.多的模型名小寫_set</b>

然后在獲取數(shù)據(jù)all(), get(), filter() 等等

如下先通過學生去獲取班級信息:

   stu = Student.objects.first()
   stu.s_grade

如下是通過班級獲取學生信息:

   g = Grade.objects.all().first()
   g.stugrade.all()   ---> 其中stugrade是定義的related_name參數(shù)

重點:

定義了related_name字段以后,只能通過related_name去反向獲取數(shù)據(jù),在也不能通過_set方法去獲取數(shù)據(jù)了
2.3 數(shù)據(jù)查詢,正查/反查
# 查詢id=4的學生的班級名稱
stu = Student.objects.get(id=4)
grade = stu.s_grade

# 查詢id=1的班級的所有學生
grade = Grade.objects.filter(id=1).first()
stus = grade.student_set.all()
2.4 練習題
2.6 獲取python班下的所有學生的信息
    gs = Grade.objects.filter(g_name='python')[0]
    allstu = gs.student_set.all()
2.7 獲取python班下語文成績大于80分的女學生
    gs = Grade.objects.filter(g_name='python')[0]
    allstu = gs.student_set.filter(stu_yuwen__gte=80)
2.8 獲取python班下語文成績超過數(shù)學成績10分的男學生
    gs = Grade.objects.filter(g_name='python')[0]
    allstu = gs.student_set.filter(stu_yuwen__gte=F('stu_shuxue') + 10)
2.9 獲取出生在80后的男學生,查看他們的班級
    gs = Grade.objects.filter(g_name='python')[0]
    allstu = gs.student_set.filter(stu_birth__gte='1980-01-01', stu_birth__lte='1990-01-01')

3. 多對多

3.1 M:N 模型

定義購物車,用戶的例子實現(xiàn)多對多:


```
1. 創(chuàng)建用戶模型:
class GoodsUser(models.Model):
u_name = models.CharField(max_length=32)

    2. 創(chuàng)建商品模型:
    class Goods(models.Model):
        g_name = models.CharField(max_length=32)
        g_user = models.ManyToManyField(User)
```
3.2 多對多表結(jié)構(gòu)
多對多關(guān)系:
1. 生成表的時候會多生成一張表(實際會有三張表)
2. 生成的表是專門用來維護關(guān)系的
3. 生成的表是使用兩個外鍵來維護多對多的關(guān)系
4. 兩個一對多的關(guān)系來實現(xiàn)多對多的實現(xiàn)   
5. 刪除一個表的數(shù)據(jù)的話,中間關(guān)聯(lián)表也要刪除相關(guān)的信息
3.3 中間表數(shù)據(jù)的增(add)刪(remove)
# id=4的用戶添加兩個商品(id=1,2)
g_user = GoodsUser.objects.get(id=4)
c1 = Goods.objects.get(id=1)
c2 = Goods.objects.get(id=2)

g_user.goods_set.add(c1)
g_user.goods_set.add(c2)


# 刪除id=4的用戶的商品中id=1的商品
g_user.goods_set.remove(c1)
3.4 練習題
3.4.1 獲取第一個用戶購買了那些商品
```
    gu = GoodsUser.objects.all().first()
    allstu = gu.goods_set.all()
```
3.4.2 獲取指定商品的購買用戶信息
```
    g = Goods.objects.filter(id=1)[0]
    g.g_user.all()
```

模板使用指南

前言

在Django框架中,模板是可以幫助開發(fā)者快速生成呈現(xiàn)給用戶頁面的工具
  模板的設(shè)計方式實現(xiàn)了我們MVT重VT的解耦,VT有著N:M的關(guān)系,一個V可以調(diào)用任意T,一個T可以供任意V使用
模板處理分為兩個過程
加載
渲染

1. 加載靜態(tài)配置文件

在settings.py中最底下有一個叫做static的文件夾,主要用來加載一些模板中用到的資源,提供給全局使用
這個靜態(tài)文件主要用來配置css,html,圖片,文字文件等

STATIC_URL = ‘/static/’
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, ‘static’)
]

只后在模板中,首先加載靜態(tài)文件,之后調(diào)用靜態(tài),就不用寫絕對全路徑了

2. 使用靜態(tài)配置文件

a) 加載渲染靜態(tài)配置文件
模板中聲明

{% load static %} 或者 {% load staticfiles %}

在引用資源的時候使用

{% static ‘xxx’ %} xxx就是相當于staticfiles_dirs的一個位置

b) 直接定義靜態(tài)配置

<img src="/static/images/mvc.png">

其中: 展示static文件夾下有一個images文件夾,下面有一個mvc.png的圖片

3. 模板摘要

3.1 模板主要有兩個部分
HTML靜態(tài)代碼
動態(tài)插入的代碼段(挖坑,填坑)也就是block
3.2 動態(tài)填充

模板中的動態(tài)代碼斷除了做基本的靜態(tài)填充,還可以實現(xiàn)一些基本的運算,轉(zhuǎn)換和邏輯
如下:


image.png

模板中的變量:
視圖傳遞給模板的數(shù)據(jù)
標準標識符規(guī)則
語法 {{ var }}
如果變量不存在,則插入空字符串

3.3 模板重的點語法
對象.屬性或者方法
索引  (student.0.name)


image.png
3.4模板中的小弊端
調(diào)用對象的方法,不能傳遞參數(shù)
3.5 模板的標簽
語法 {% tag %}
作用 a)加載外部傳入的變量
     b)在輸出中創(chuàng)建文本
     c)控制循環(huán)或邏輯

4. if表達式

格式1:

    {% if 表達式 %}

    {%  endif %}

格式2:

    {% if表達式 %}

    {% else %}

    {%  endif %}

格式3:

    {% if表達式 %}

    {% elif 表達式 %}

    {%  endif %}


image.png

5. for表達式

格式1:

    {% for 變量 in 列表 %}

    {% empty %}

    {% endfor %}


image.png

注意:當列表為空或者不存在時,執(zhí)行empty之后的語句

注意一下用法:
{{ forloop.counter }} 表示當前是第幾次循環(huán),從1開始
{{ forloop.counter0 }} 表示當前從第幾次循環(huán),從0開始
{{forloop.revcounter}}表示當前是第幾次循環(huán),倒著數(shù)數(shù),到1停
{{forloop.revcounter0}}表示當前是第幾次循環(huán),倒著數(shù)數(shù),到0停
{{forloop.first}}是否是第一個      布爾值
{{forloop.last}}是否是最后一個      布爾值

6. 注釋

6.1 注釋可見,可運行
<!-- 注釋內(nèi)容 -->
6.1 單行注釋注釋不可見,不可運行

單行注釋(頁面源碼中不會顯示注釋內(nèi)容)

{# 被注釋掉的內(nèi)容 #}
6.2 多行注釋注釋不可見,不可運行
{% comment %}

{% endcomment %}


image.png

7. 過濾器

引入過濾器定義:{{var|過濾器}}, 作用:在變量顯示前修改
過濾器有很多,比如add / lower / upper

7.1 加法
    {{ p.page | add:5 }}
    沒有減法的過濾器,但是加法里面可以加負數(shù)
    {{ p.page | add: -5 }}
7.2 修改大小寫
    lower / upper : {{ p.pname | lower }} 變?yōu)樾懟蛘叽髮?
7.3 傳參數(shù)

過濾器可以傳遞參數(shù),參數(shù)需要使用引號引起來。比如join: {{ student | join ‘=’ }}
如果值為空則設(shè)置默認值:

    默認值:default,格式{{ var | default value }}
    如果變量沒有被提供或者為False,空,會使用默認值
7.4 定制日期格式

根據(jù)制定格式轉(zhuǎn)換日期為字符串,處理時間的就是針對date進行的轉(zhuǎn)換

{{ dateVal | date: ‘y-m-d h:m:s’ }}

如果過濾器,定義為小寫的y,則返回的數(shù)據(jù)為兩位的年。如果寫的是大寫的Y,則返回的是四位的年

定義小寫的m,則返回數(shù)字的月份,如果定義大寫的M,則返回英文

定義小寫的h,則返回12小時制度的時,如果定義的是大寫的H,則返回24小時制度的時

7.5 是否轉(zhuǎn)義

HTML轉(zhuǎn)義:
將接收到的數(shù)據(jù)當成普通字符串處理還是當成HTML代碼來渲染的一個問題
渲染成html: {{ code | safe }}
還可以使用autoscape渲染:
{{ autoscape off }}
{{ endautoscape }}
不渲染的話:
{{ autoscape on }}
{{ endautoscape }}

7.6 案例
<!--1. 字符串‘Python’轉(zhuǎn)化為大寫,輸出結(jié)果為:PYTHON-->
{{ 'Python'|upper }}
<!--2. 字符串‘PYTHON’轉(zhuǎn)化為小寫,輸出結(jié)果為:python-->
{{ 'PYTHON'|lower }}
<!--3. 變量3增加4,輸出結(jié)果為:7-->
{{ 3|add:'4' }}
<!--4. 第一個字符轉(zhuǎn)化成大寫形式,輸出結(jié)果為:Python-->
{{ 'python'|capfirst }}
<!--5. 刪除指定符號的值,輸出結(jié)果為:studypythonisveryhappy -->
{{ 'study python is very happy'|cut:' ' }}
<!--6. 輸出缺省值,輸出結(jié)果為:nothing-->
{{ ''|default:'nothing' }}
<!--7. 返回第一個元素,輸出結(jié)果為:p-->
{{ 'python'|first }}
<!--8. 返回最后一個元素,輸出結(jié)果為:n-->
{{ 'python'|last }}
<!--9. 計算長度,輸出結(jié)果為:6-->
{{ 'python'|length }}
<!--10. 隨機一個元素,輸出隨機結(jié)果為:y-->
{{ 'python'|random }}
7.7 django內(nèi)建過濾器大全
1、add :將value的值增加2。使用形式為:{{ value | add: "2"}}。
2、addslashes:在value中的引號前增加反斜線。使用形式為:{{ value | addslashes }}。
3、capfirst:value的第一個字符轉(zhuǎn)化成大寫形式。使用形式為:{{ value | capfirst }}。
4、cut:從給定value中刪除所有arg的值。使用形式為:{{ value | cut:arg}}。
5、date: 格式化時間格式。使用形式為:{{ value | date:"Y-m-d H:M:S" }}
6、default:如果value是False,那么輸出使用缺省值。使用形式:{{ value | default: "nothing" }}。例如,如果value是“”,那么輸出將是nothing
7、default_if_none:如果value是None,那么輸出將使用缺省值。使用形式:{{ value | default_if_none:"nothing" }},例如,如果value是None,那么輸出將是nothing
8、dictsort:如果value的值是一個字典,那么返回值是按照關(guān)鍵字排序的結(jié)果
使用形式:{{ value | dictsort:"name"}},例如,
如果value是:
[{'name': 'python'},{'name': 'java'},{'name': 'c++'},]
那么,輸出是:
[{'name': 'c++'},{'name': 'java'},{'name': 'python'}, ]
9、dictsortreversed:如果value的值是一個字典,那么返回值是按照關(guān)鍵字排序的結(jié)果的反序。使用形式:與dictsort過濾器相同。
10、divisibleby:如果value能夠被arg整除,那么返回值將是True。使用形式:{{ value | divisibleby:arg}},如果value是9,arg是3,那么輸出將是True
11、escape:替換value中的某些字符,以適應HTML格式。使用形式:{{ value | escape}}。例如,< 轉(zhuǎn)化為 &lt;> 轉(zhuǎn)化為 &gt;' 轉(zhuǎn)化為  &#39;" 轉(zhuǎn)化為  &quot;
13、filesizeformat:格式化value,使其成為易讀的文件大小。使用形式:{{ value | filesizeformat }}。例如:13KB,4.1MB等。
14、first:返回列表/字符串中的第一個元素。使用形式:{{ value | first }}
16、iriencode:如果value中有非ASCII字符,那么將其進行轉(zhuǎn)化成URL中適合的編碼,如果value已經(jīng)進行過URLENCODE,改操作就不會再起作用。使用形式:{{value | iriencode}}
17、join:使用指定的字符串連接一個list,作用如同python的str.join(list)。使用形式:{{ value | join:"arg"}},如果value是['a','b','c'],arg是'//'那么輸出是a//b//c
18、last:返回列表/字符串中的最后一個元素。使用形式:{{ value | last }}
19、length:返回value的長度。使用形式:{{ value | length }}
20、length_is:如果value的長度等于arg的時候返回True。使用形式:{{ value | length_is:"arg"}}。例如:如果value是['a','b','c'],arg是3,那么返回True
21、linebreaks:value中的"\n"將被<br/>替代,并且整個value使用</p>包圍起來。使用形式:{{value|linebreaks}}
22、linebreaksbr:value中的"\n"將被<br/>替代。使用形式:{{value |linebreaksbr}}
23、linenumbers:顯示的文本,帶有行數(shù)。使用形式:{{value | linenumbers}}
24、ljust:在一個給定寬度的字段中,左對齊顯示value。使用形式:{{value | ljust}}
25、center:在一個給定寬度的字段中,中心對齊顯示value。使用形式:{{value | center}}
26、rjust::在一個給定寬度的字段中,右對齊顯示value。使用形式:{{value | rjust}}
27、lower:將一個字符串轉(zhuǎn)換成小寫形式。使用形式:{{value | lower}}
30、random:從給定的list中返回一個任意的Item。使用形式:{{value | random}}
31、removetags:刪除value中tag1,tag2....的標簽。使用形式:{{value | removetags:"tag1 tag2 tag3..."}}
32、safe:當系統(tǒng)設(shè)置autoescaping打開的時候,該過濾器使得輸出不進行escape轉(zhuǎn)換。使用形式:{{value | safe}}
33、safeseq:與safe基本相同,但有一點不同的就是:safe是針對字符串,而safeseq是針對多個字符串組成的sequence
34、slice:與python語法中的slice相同。使用形式:{{some_list | slice:"2"}}
37、striptags:刪除value中的所有HTML標簽.使用形式:{{value | striptags}}
38、time:格式化時間輸出。使用形式:{{value | time:"H:i"}}或者{{value | time}}
39、title:轉(zhuǎn)換一個字符串成為title格式。
40、truncatewords:將value切成truncatewords指定的單詞數(shù)目。使用形式:{{value | truncatewords:2}}。例如,如果value是Joel is a slug 那么輸出將是:Joel is ...
42、upper:轉(zhuǎn)換一個字符串為大寫形式
43、urlencode:將一個字符串進行URLEncode
46、wordcount:返回字符串中單詞的數(shù)目

8. 運算

8.1 乘
    {% widthratio 數(shù) 分母 分子 %}

如下例子: 求數(shù)學成績的10倍的結(jié)果
{% widthratio 10 1 stu.stu_shuxue %}

8.2 整除

{{ num|divisibleby:2 }}
注意:該語句的意思是,判斷num值是否能被2整除,如果能的話返回True,不能的話返回False

8.3 ifeuqal判斷相等

{% ifequal value1 value2 %}

{% endifqueal %}

image.png

9. 反向解析

Url 反向解析
{% url ‘namespace:name’ p1 p2 %}

image.png

10. 跨站請求CSRF(Cross Site Request Forgery)

csrf攻擊說明

1.用戶C打開瀏覽器,訪問受信任網(wǎng)站A,輸入用戶名和密碼請求登錄網(wǎng)站A;

2.在用戶信息通過驗證后,網(wǎng)站A產(chǎn)生Cookie信息并返回給瀏覽器,此時用戶登錄網(wǎng)站A成功,可以正常發(fā)送請求到網(wǎng)站A;

3.用戶未退出網(wǎng)站A之前,在同一瀏覽器中,打開一個TAB頁訪問網(wǎng)站B;

4.網(wǎng)站B接收到用戶請求后,返回一些攻擊性代碼,并發(fā)出一個請求要求訪問第三方站點A;

5.瀏覽器在接收到這些攻擊性代碼后,根據(jù)網(wǎng)站B的請求,在用戶不知情的情況下攜帶Cookie信息,向網(wǎng)站A發(fā)出請求。網(wǎng)站A并不知道該請求其實是由B發(fā)起的,所以會根據(jù)用戶C的Cookie信息以C的權(quán)限處理該請求,導致來自網(wǎng)站B的惡意代碼被執(zhí)行。

csrf的攻擊之所以會成功是因為服務器端身份驗證機制可以通過Cookie保證一個請求是來自于某個用戶的瀏覽器,但無法保證該請求是用戶允許的。因此,預防csrf攻擊簡單可行的方法就是在客戶端網(wǎng)頁上添加隨機數(shù),在服務器端進行隨機數(shù)驗證,以確保該請求是用戶允許的。Django也是通過這個方法來防御csrf攻擊的。

理解如下圖:


image.png

Django中防止跨站請求偽造使用CSRF, 即:客戶端訪問服務器端,在服務器端正常返回給客戶端數(shù)據(jù)的時候,而外返回給客戶端一段字符串,等到客戶端下次訪問服務器
端時,服務器端會到客戶端查找先前返回的字符串,如果找到則繼續(xù),找不到就拒絕。

Django中配置:

  1. 在表單中添加
    {% csrf_token %}
  2. 在settings中的中間件MIDDLEWARE中配置打開
    ‘django.middleware.csrf.CsrfViewMiddleware’

11. 模板繼承

11.1 block挖坑不用看了
關(guān)鍵字 block挖坑
{% block xxx %}
{% endblock %}
11.2 extends
extends 繼承,寫在開頭位置
{% extends ‘父模板路徑’%}
11.3 include
include 加載模型進行渲染
{% include ‘模板文件’%}

12. 模板繼承實戰(zhàn)

12.1 定義基礎(chǔ)模板base.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            {% block title %}
            {% endblock %}
        </title>
        {% block extCSS %}
        {% endblock %}
        {% block extJS %}
        {% endblock %}
    </head>
    {% block indexbody %}
    {% endblock %}
    <body>

    {% block content %}
    {% endblock %}

    {% block footer %}
    {% endblock %}
    </body>
</html>
12.2 定義繼承base.html的base_main.html模板

該base_main.html模板主要用于加載一些公共的js或者css,其余模板繼承該模板后,可以直接加載定義好的公共的js或者css

{% extends 'base.html' %}

{% block extJS %}
    <script type="text/javascript" src="/static/js/jquery.min.js"></script>
{% endblock %}
12.3 定義首頁index.html

在首頁index.html中,我們在{% block extJS %}中使用{{ block.super }}去加載之前在base_main.html中定義好了的js文件,將它繼承過來,那么在index.html中就會加載兩個js文件了。實現(xiàn)了將公共的js文件或者css文件單獨提煉出去,不需要再每個頁面中重復的去寫加載js的重復代碼了。

{% extends 'base_main.html' %}

{% block title %}
    首頁{{ user.username }}
{% endblock %}

{% block extCSS %}
    <link rel="stylesheet" type="text/css" href="/static/css/public.css" />
{% endblock %}

{% block extJS %}
    {{ block.super }}
    <script type="text/javascript" src="/static/js/public.js"></script>
{% endblock %}

{% block indexbody %}
<frameset rows="100,*" cols="*" scrolling="No" framespacing="0"
    frameborder="no" border="0">
    <frame src="{% url 'app:head' %}" name="headmenu" id="mainFrame" title="mainFrame"><!-- 引用頭部 -->
<!-- 引用左邊和主體部分 -->
    <frameset rows="100*" cols="220,*" scrolling="No"
    framespacing="0" frameborder="no" border="0">
        <frame src="{% url 'app:left' %}" name="leftmenu" id="mainFrame" title="mainFrame">
        <frame src="{% url 'app:grade' %}" name="main" scrolling="yes" noresize="noresize"
    id="rightFrame" title="rightFrame">
    </frameset>
</frameset>
{% endblock %}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容