Django 基礎1css
day49html
老師的博客:
https://www.cnblogs.com/yuanchenqi/articles/6083427.html前端
http://www.cnblogs.com/haiyan123/p/7701412.htmlpython
MVC和MTV模型:jquery
著名的MVC模式:所謂MVC就是把web應用分爲模型(M),控制器(C),視圖(V,html文件)三層;他們之間以一種插件似的,鬆耦合的方式鏈接在一塊兒。web
模型負責業務對象與數據庫的對象(ORM),視圖負責與用戶的交互(頁面),控制器(C)接受用戶的輸入調用模型和視圖完成用戶的請求。數據庫
Django的MTV模式本質上與MVC模式沒有什麼差異,也是各組件之間爲了保持鬆耦合關係,只是定義上有些許不一樣,Django的MTV分別表明:django
Model(模型):負責業務對象與數據庫的對象(ORM)瀏覽器
Template(模版,html文件):負責如何把頁面展現給用戶服務器
View(視圖):負責業務邏輯,並在適當的時候調用Model和Template
此外,Django還有一個url分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Template
Django 的流程和命令行工具
安裝django
pip3 install django---->添加環境變量
建立項目(工程)
django-admin startproject p2p
---p2p(下面的文件是全局的)
---settings.py 配置
---urls.py 路由分發
---wsgi.py web
---manage.py
建立應用(App),咱們的app01 的應用寫在這裏
python manage.py startapp app01
咱們建立了一個app01 後,咱們要到全局配置p2p/settings.py 裏 INSTALLED_APPS 添加一行 「app01」
如今咱們給app01 這個應用添加一個show_time 的功能,由於咱們的全部的邏輯是寫在views裏,因此咱們在app01/views.py 裏定義以下函數
def show_time():
pass
而後咱們在全局路由urls.py裏配置路由轉發規則
from app01 import views
path('show_time/', views.show_time)
django2 這裏是urls(r'show_time/', views.show_time)
django3 這裏是path
由於咱們返回的是字符串給瀏覽器,因此這裏咱們引入HttpResponse
from django.shortcuts import render,HttpResponse
def show_time(request):
return HttpResponse("hello")
咱們把全部的靜態文件放在template 目錄下,這裏咱們修改一下settings.py
註釋掉
# TEMPLATE_DIRS = (os.path.join(BASE_DIR,'templates'),)
在
TEMPLATES 列表裏的字典 DIRS=[] 改爲
'DIRS': [os.path.join(BASE_DIR,'templates')]
咱們的views.py 這麼寫
from django.shortcuts import render,HttpResponse import time # Create your views here. def show_time(request): # return HttpResponse("hello world") local_time=time.ctime() return render(request,"index.html",{"time":local_time})
這裏的 {"time":local_time} 渲染給前端。前端經過{{ time }}來接收參數
templates 下的index.html 這麼寫。這裏兩個大括號的做用就是渲染 time 變量
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>hello bigbao {{ time }}</h1> </body> </html>
這裏咱們用前面學到的jquery知識,咱們把前端展現的字體變成紅色(錯誤示範)
一、咱們把jqeuery-3.1.1.js文件放到templates目錄下
二、index.html 作以下調整
<h1>hello bigbao {{ time }}</h1> <script src="jquery-3.1.1.js"></script> <script> $("h1").css("color","red") </script>
三、咱們再去訪問一下,看到字體顏色沒有變化,報以下的錯誤
這裏錯誤的緣由是Django沒有找到這個jquery文件
這裏咱們應該在項目裏面建立一個static目錄(和應用同級),這個咱們後面放js,css,img
而後咱們把jquery文件放在staic目錄下,而後咱們在settings.py 裏進行配置,讓Django知道靜態文件放在哪裏了
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]
這裏必須用 STATICFILES_DIRS 這個名字,同時別忘了 逗號
這裏說一個問題,我一開始試驗的時候,我這裏建立的目錄的名字是statics ,而後我這裏配置的是
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'statics'),]
可是訪問的時候仍是404,我這裏用上面那種方法就是能夠用的。如今咱們解釋一下
STATIC_URL 和 STATICFILES_DIRS
STATICFILES_DIRS 是告訴Django 的static的絕對路徑,可是引用的時候用的是STATIC_URL
# STATIC_URL 是別名,之後實際用的時候用的是這個別名,STATICFILES_DIRS 是Django用的,STATICFILES_DIRS 和 STATIC_URL 必須都存在,結合使用的
# 咱們在用STATIC_URL別名的時候,Django 會本身去找到他的實際路徑,咱們在html應用靜態文件的時候必須用別名,好比
# <script src="/static/jquery.js"></script>
# 文件的實際存在目錄,必須叫STATICFILES_DIRS
因此咱們index.html 用下面的方式就能夠改變頁面的字體顏色了
<h1>hello bigbao {{ time }}</h1> <script src="/static/jquery-3.1.1.js"></script> 這裏的static用的是配置文件的別名 <script> $("h1").css("color","red") </script>
再說一下上面的問題,假如說咱們的靜態文件的真實路徑的名字是 bigbao_static 那麼這裏咱們的settings.py配置是這樣的 ------------------------------------------------------------------------------------------- STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'bigbao_static'),] ------------------------------------------------------------------------------------------- html 文件是這樣的 <h1>hello bigbao {{ time }}</h1> <script src="/static/jquery-3.1.1.js"></script> <script> $("h1").css("color","red") </script> 由於這裏咱們的別名是static,記住這句話 STATIC_URL 和 STATICFILES_DIRS 是想呼應的,STATICFILES_DIRS 是給Django用的,他去找真實的路徑,STATIC_URL別名是給後面項目實際調用的 因此咱們在html文件裏要是寫真實的靜態文件路徑是不行的 <script src="/bigbao_static/jquery-3.1.1.js"></script>
還有一種方案就是load,後面推薦使用的,可是咱們剛剛前面配置的STATIC_URL 和 STATICFILES_DIRS不能註釋掉,咱們在html文件裏這麼寫
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% load staticfiles %} <title>Title</title> </head> <body> <h1>hello bigbao {{ time }}</h1> {#<script src="/static/jquery-3.1.1.js"></script>#} {% static "jquery-3.1.1.js" %} <script> $("h1").css("color","red") </script> </body> </html>
其實在實際工做中咱們應該把每一個app的靜態文件放在本身應用的目錄下面,因此這裏咱們在本身的應用目錄下面app01建立一個static目錄
而後配置settings.py STATICFILES_DIRS=[os.path.join(BASE_DIR,"app01","static")]
Django的URL控制系統
URL 的無名分組和有名分組
from app02 import views from django.conf.urls import url urlpatterns = [ #無名分組 url(r'^article/\d{4}', views.year) , url(r'^article/(\d{4})$', views.year2), 若是有多個匹配同樣的時候,誰放在上面就匹配誰,上面的就會把下面的覆蓋了 正則加上括號,就是分組,會把分組的內容做爲year2函數的參數傳進去 url(r'^article/(\d{4})/(\d{2})$', views.year_month), # 有名分組(就是給分組起個名字,這樣定義的好處就是按照關鍵字參數去傳參了,指名道姓的方式) url(r'^article/(?P<year>\d{4})/(?P<month>\d{2})$', views.year_month_hasname)
捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:
/articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數
這裏咱們也一個簡單的註冊頁面;
urls.py path('register/', views.register,name="reg"), 這裏的name 是一個別名,後面用這個別名 ----------------------------------------------------------------------------------------------------------------------------------views.py-------------------------------------------def register(request,*args,**kwargs): if request.method == "POST": # print(request.POST.get('username')) print(request.POST) return HttpResponse("Success") return render(request,"register.html") ----------------------------------------------------------------------------------------------------------------------------------register.html-------------------------------------- <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> *{ padding: 0; margin: 0; } h1{ text-align: center; } </style> </head> <body> <h1>註冊系統</h1> <form action="{% url 'reg' %}" method="post"> {#<form action="/register" method="get">#} {# 這倆action 路徑寫死了,這個時候咱們應該在 urlpattern 上家一個別名#} <p>姓名<input type="text" name="username"></p> <p>年齡<input type="text" name="age"></p> <p>愛好<input type="checkbox" name="hobby" value="1">籃球 <input type="checkbox" name="hobby" value="2">網球 <input type="checkbox" name="hobby" value="3">足球 </p> <p><input type="submit" value="提交數據"></p> </form> </body> </html>
實際環境中咱們應該根據應用來分發URL,因此這裏咱們應該用URLConf
操做方式是:
咱們在項目下的主路由urls.py作以下修改
from django.urls import path 改爲 from django.urls import path,include
path('app01/', include('app01.urls')) 全部已app01 開頭的都跳到app01.urls路由
而後咱們到app01 下建立urls.py文件
from django.urls import path
from app01 import views
urlpatterns = [
path('register/', views.register,name="reg"),
]
這個時候咱們就不能用剛的方式去訪問了http://127.0.0.1:8000/register/這樣是訪問不到的
咱們得用這種方式 http://127.0.0.1:8000/app01/register/
view(視圖)和template(模板)day50
http請求產生兩個核心對象
httpRequest
httpResponse
HTTPRequest的屬性和方法:
# path: 請求頁面的全路徑,不包括域名 # # method: 請求中使用的HTTP方法的字符串表示。全大寫表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含全部HTTP GET參數的類字典對象 # # POST: 包含全部HTTP POST參數的類字典對象 # # 服務器收到空的POST請求的狀況也是可能發生的,也就是說,表單form經過 # HTTP POST方法提交請求,可是表單中可能沒有數據,所以不能使用 # if req.POST來判斷是否使用了HTTP POST 方法;應該使用 if req.method=="POST" # # # # COOKIES: 包含全部cookies的標準Python字典對象;keys和values都是字符串。 # # FILES: 包含全部上傳文件的類字典對象;FILES中的每個Key都是<input type="file" name="" />標籤中 name屬性的值,FILES中的每個value同時也是一個標準的python字典對象,包含下面三個Keys: # # filename: 上傳文件名,用字符串表示 # content_type: 上傳文件的Content Type # content: 上傳文件的原始內容 # # # user: 是一個django.contrib.auth.models.User對象,表明當前登錄的用戶。若是訪問用戶當前 # 沒有登錄,user將被初始化爲django.contrib.auth.models.AnonymousUser的實例。你 # 能夠經過user的is_authenticated()方法來辨別用戶是否登錄: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 時該屬性纔可用 # # session: 惟一可讀寫的屬性,表明當前會話的字典對象;本身有激活Django中的session支持時該屬性纔可用。 #方法 get_full_path(), 好比:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()獲得的結果就是/index33/?name=123 req.path:/index33 full_path 拿到的含有參數
HtppResponse 對象
HttpResponse類在django.http.HttpResponse
render 和 render_to_response 的區別是render_to_response的第一個參數不用寫request,效果都是頁面渲染
render(request,"register.html")
render_to_resonse("register.html")
這裏推薦使用render
locals()--->局部變量 將函數文件中的全部變量傳遞給模板,這裏咱們建議不要使用locals(函數中的變量名得和模板文件中的變量名一致,咱們也能夠在模板文件中直接調用局部變量request.method),最好是指定變量傳遞模板文件,好比說render(request,"register.html",{"time":t,"username":name})
redirect
redirect(「/login/」) 頁面跳轉,register.html---->return redirect("login")---->urlpattern---->view---->def login()---->login.html---->咱們能夠看到瀏覽器的URL地址也發生了變化,從register到login
template(模板)
一、模板的組成:
HTML代碼+python邏輯控制代碼
二、邏輯控制代碼的組成
2.一、變量(使用雙大括號來應用變量)
html引用格式:{{ var_name }}
深度查詢(萬能的句點號)
.索引 --->列表
.key --->字典
變量的過濾器
語法格式: {{obj|filter:param}}
# 1 add : 給變量加上相應的值
#
# 2 addslashes : 給變量中的引號前加上斜線
#
# 3 capfirst : 首字母大寫
#
# 4 cut : 從字符串中移除指定的字符
#
# 5 date : 格式化日期字符串
#
# 6 default : 若是值是False,就替換成設置的默認值,不然就是用原本的值
#
# 7 default_if_none: 若是值是None,就替換成設置的默認值,不然就使用原本的值
#實例:
#value1="aBcDe"
{{ value1|upper }}<br> 字母所有大寫
#value2=5
{{ value2|add:3 }}<br> 加3
#value3='he llo wo r ld'
{{ value3|cut:' ' }}<br> 去除指定字符串
#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br> 時間格式化
#value5=[]
{{ value5|default:'bigbao' }}<br> 當取指定字符串的時候,沒有的狀況下給他設置一個默認值
#value6='<a href="#">跳轉</a>'
{{ value6 }}
{% autoescape off %}
{{ value6 }}
{% endautoescape %}
{{ value6|safe }}<br>
{{ value6|striptags }}
#value7='1234'
{{ value7|filesizeformat }}<br>
{{ value7|first }}<br>
{{ value7|length }}<br>
{{ value7|slice:":-1" }}<br>
#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}<br>
value9='hello I am yuan'
<h1>{{ name_list.4|default:'h e l l o ' |upper|cut:" " }}</h1>
模板中if 和 for 循環:{% 標籤 %}
標籤的使用tag(使用大括號和百分號的組合來使用tag)
view ---------------------------------------------- def query(request): name_list=['bigbao','z ho ng','xiaohu'] d={'name':'bigbao','age':18,'hobby':'girl'} return render(request,"index.html",locals()) ------------------------- html,這裏的if 能夠嵌套if ------------------------- {% if d.age < 15 %} <h1> hello {{ d.name }}</h1> {% elif d.age == 20 %} <h1>hello {{ d.hobby }}</h1> {% else %} <h1>hello {{ d.age }}</h1> {% endif %}
{% if %} 標籤接受and,or或者not來測試多個變量值或者否認一個給定的變量
{% if %} 標籤不容許同一標籤裏同時出現and和or,不然邏輯容易產生歧義,例以下面的標籤是不合法的:
{% if obj1 and obj2 or obj3 %}
forloop.counter 就是一個計數器,循環的次數,從1開始,可是要是forloop.counter0 就是從0開始計數了 {% for foo in name_list %} <h1>{{ forloop.counter }} : {{ foo }}</h1> {% endfor %}
還有一些其餘的標籤以及自定義標籤,看一下老師的博客
模板繼承(extend)
正常狀況下,咱們有一部分樣式是想保持不變的。這個時候各個頁面都要繼承這個基礎樣式,有特殊需求的能夠在本身的頁面進行修改。好比說下面這個例子
----------------------------------url.py----------------------------------------------- path('backend/',views.backend), path('teacher/',views.teacher,name="teacher"), path('student/',views.student,name="student"), ---------------------------------views.py--------------------------------------------- def backend(request): return render(request,'backend.html') def teacher(request): teacher_list=['teacher_1','teacher_2','teacher_3'] return render(request,'teacher.html',locals()) def student(request): student_list=['student_A','student_B','student_C'] return render(request,'student.html',{'student':student_list}) --------------------------base.html------------------------------------------------------ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> {% block style %} {% endblock %} </title> <script src="/static/jquery-3.1.1.js"></script> <style> * { margin: 0; padding: 0; } .nav{ line-height: 40px; width: 100%; background-color: #2459a2; color: white; font-size: 20px; text-align: center; } .left{ float: left; width:20%; min-height: 600px; overflow: auto; background-color: #ededed; } .manager{ text-align: center; padding: 20px 0; margin: 15px 0; font-size: 18px; } a { text-decoration: none; } .content{ float: left; width: 70%; min-height: 600px; text-align: center; } h3{ color: red; font-size: 50px; } </style> </head> <body> <div class="outer"> <div class="nav">標題</div> <div class="left"> <div class="teacher manager"><a href="/teacher/">老師管理</a></div> <div class="student manager"><a href="/student/">學生管理</a></div> <div class="course manager"><a href="">課程管理</a></div> <div class="classes manager"><a href="">班級管理</a></div> </div> <div class="content"> {% block content %} {% endblock %} </div> </div> </body> </html> -----------------------------------backend.html------------------------------------- {% extends "base.html" %} {% block content %} <h1> Welcome To BigBaoOps</h1> {% endblock %} ---------------------------------teacher.html---------------------------------------- {% extends "base.html" %} {% block style %} Teacher Page {% endblock %} {% block content %} {% for foo in teacher_list %} <h2>{{ foo }}</h2> {% endfor %} {% endblock %} ---------------------------------teacher.html----------------------------------------- {% extends "base.html" %} {% block style %} Student Page {% endblock %} {% block content %} {% for foo in student %} <h3>{{ foo }}</h3> {% endfor %} {% endblock %}
這裏咱們在base.html 上指定的標籤上添加一個block,好比這裏我給了個人title和個人content分別設置了block
而後在咱們的子模塊上的第一行永遠是
{% extends "base.html" %}
而後對本身的 block 作格式設置以及文字添加
注意:
<1>若是在模板中使用 {% extends %} ,必須保證其爲模板中的第一個模板標記。 不然,模板繼承將不起做用。 <2>通常來講,基礎模板中的 {% block %} 標籤越多越好。 記住,子模板沒必要定義父模板中全部的代碼塊,所以 你能夠用合理的缺省值對一些代碼塊進行填充,而後只對子模板所需的代碼塊進行(重)定義。 俗話說,鉤子越 多越好。 <3>若是發覺本身在多個模板之間拷貝代碼,你應該考慮將該代碼段放置到父模板的某個 {% block %} 中。 若是你須要訪問父模板中的塊的內容,使用 {{ block.super }}這個標籤吧,這一個魔法變量將會表現出父模 板中的內容。 若是隻想在上級代碼塊基礎上添加內容,而不是所有重載,該變量就顯得很是有用了。 <4>不容許在同一個模板中定義多個同名的 {% block %} 。 存在這樣的限制是由於block 標籤的工做方式是雙向的。 也就是說,block 標籤不只挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。若是模板中出現了兩個 相同名稱的 {% block %} 標籤,父模板將無從得知要使用哪一個塊的內容。
include 擴展模塊
在講解了模板加載機制以後,咱們再介紹一個利用該機制的內建模板標籤: {% include %} 。該標籤容許在(模板中)包含其它的模板的內容。 標籤的參數是所要包含的模板名稱,
能夠是一個變量,也能夠是用單/雙引號硬編碼的字符串。 每當在多個模板中出現相同的代碼時,就應該考慮是否要使用 {% include %} 來減小重複。
好比說咱們如今有一個test.html ,可是咱們想在 student.html 裏面加載test.html 的內容
那麼咱們就在student.html 作以下設置
{% load staticfiles %}
而後在你想要的位置引入test.html 的內容的地方作以下設置
{% include "test.html" %}