django 路由層(反向解析)03

ORM表關係創建

orm表關係如何創建
多對多
一對多
一對一
換位思考 先站在一張表上面分析 而後再站在另外一張分析html

一對多 外鍵字段建在 多的那一方
多對多 多對多的外鍵關係須要創建第三章來專門處理

圖書表 
出版社表
做者表

from django.db import models

# Create your models here.
# 先不要考慮外鍵關係  先創基表
class Book(models.Model):
    title = models.CharField(max_length=32)
    # 小數總共八位 小數佔兩位
    price = models.DecimalField(max_digits=8,decimal_places=2)
    # 書跟出版社是一對多 而且書是多的一方 因此外鍵字段健在書表中
    publish_id = models.ForeignKey(to='Publish')  # to用來指代跟哪張表有關係 默認關聯的就是表的主鍵字段
"""
一對多外鍵字段 建立的時候 同步到數據中 表字段會自動加_id後綴
若是你本身加了_id 我orm頭鐵 再在後面加一個_id
因此你在寫一對多外鍵字段的時候 不要自做聰明的加_id
"""

    # 書跟做者是多對多的關係 外鍵字段建在任意一方均可以  可是建議你建在查詢頻率較高的那一方
    author = models.ManyToManyField(to='Author')  # django orm會自動幫你建立書籍 和做者的第三張關係表
    # author這個字段是一個虛擬字段 不能在表中展現出來 僅僅只是起到一個高速orm 建第三章表的關係的做用

class Publish(models.Model):
    title = models.CharField(max_length=32)
    email = models.EmailField()


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    # 一對一的表關係 外鍵字段建在任意一方均可以    可是建議你建在查詢頻率較高的那一方
   author_detail = models.OneToOneField(to='Author_detail')  # fk + unique
"""
一對一外鍵字段 建立的時候 同步到數據中 表字段會自動加_id後綴
若是你本身加了_id 我orm頭鐵 再在後面加一個_id
因此你在寫一對一外鍵字段的時候 不要自做聰明的加_id
"""
class Author_detail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=32)

Django請求生命週期流程圖

urls.py 路由層

django路由匹配規律:不加斜槓,先匹配一次,若是匹配不上,會讓瀏覽器重定向,加一個斜槓再匹配一次前端

url第一個參數是一個正則表達式 只要該正則表達式可以匹配到內容,就會馬上執行後面的視圖函數 而再也不往下繼續匹配了。python

# settings配置文件中加上:

# 取消django自動讓瀏覽器增長斜槓
APPEND_SLASH = False # 該參數默認是True
'''
加上這句話,瀏覽器端若是後綴不加斜槓就會自動報錯,後端不在自動加斜槓讓瀏覽器再請求一次
'''
urlpatterns = [
    url(r'^admin/', admin.site.urls) ,  # url第一個參數是一個正則表達式
    url(r'^test/$', views.test),   # 一旦正則表達式可以匹配到內容 會馬上結束匹配關係 直接執行後面對應的函數
    url(r'testddd/$', views.testddd),
]
# django匹配路由的規律
# 不加斜槓 先匹配一次試試 若是匹配不上 會讓瀏覽器重定向 加一個斜槓再來一次 若是還匹配不上 纔會報錯
"""
路由匹配值匹配url部分
不匹配?後面的get攜帶的參數
"""

無名分組

無名分組:將分組內正則表達式匹配到的內容當作位置參數傳遞給視圖函數
    url(r'^test/([0-9]{4})/', views.test)
    url(r'^test/(\d+)/', views.test),  # 匹配一個或者多個數字
    test() takes 1 positional argument but 2 were given

# 當你的路由中有分組的正則表達式  那麼在匹配到內容
# 執行視圖函數的時候 會將分組內正則表達式匹配到的內容當作位置參數傳遞給視圖函數  test(request,分組內正則表達式匹配到的內容)

有名分組

有名分組(將加括號的正則表達式匹配到的內容當作關鍵字參數自動傳遞給對應的視圖函數)
        url(r'^test/(?P<year>\d+)/',views.test),  #將匹配到的數字起別名,叫year,做爲關鍵字參數傳給視圖函數
        
        def test(request,year):
            print(year)
            return HttpResponse('test')
    
        注意:無名分組和有名分組不能混着用!!!
            url(r'^test/(\d+)/(?P<year>\d+)/',views.test)
# 可是支持用一類型多個形式匹配
# 無名分組多個
url(r'^test/(\d+)/(\d+)/',views.test),
# 有名分組多個
url(r'^test/(?P<year>\d+)/(?P<xxx>\d+)/',views.test),

反向解析

無名分組的反向解析

第一種狀況:jquery

"""
根據一個別名 動態解析出一個結果 該結果能夠直接訪問對應的url
"""
# 路由中沒有正則表達式 直接是寫死的
url(r'^home/', views.home,name='xxx'),  # 給路由與視圖函數對應關係起別名
            
# 前端反向解析
{% url 'xxx' %}

# 後端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
url = reverse('xxx')

第二種狀況:git

無名分組的反向解析 在解析的時候 你須要手動指定正則匹配的內容是什麼
            url(r'^home/(\d+)/', views.home,name='xxx'),  # 給路由與視圖函數對應關係起別名
前端反向解析
<p><a href="{% url 'xxx' 12 %}">111</a></p>
<p><a href="{% url 'xxx' 1324 %}">111</a></p>
<p><a href="{% url 'xxx' 14324 %}">111</a></p>
<p><a href="{% url 'xxx' 1234 %}">111</a></p>

後端反向解析
url = reverse('xxx',args=(1,))
url1 = reverse('xxx',args=(3213,))
url2 = reverse('xxx',args=(2132131,))
# 手動傳入的參數 只須要知足可以被正則表達式匹配到便可

有名分組的反向解析

第三種狀況正則表達式

'''
有名分組的反向解析 在解析的時候 你須要手動指定正則匹配的內容是什麼
有名分組的反向解析能夠跟無名分組同樣
'''
url(r'^home/(?P<year>\d+)/', views.home,name='xxx'),  # 給路由與視圖函數對應關係起別名
            
前端
# 能夠直接用無名分組的狀況
<p><a href="{% url 'xxx' 12 %}">111</a></p>
# 你也能夠規範寫法
<p><a href="{% url 'xxx' year=1232 %}">111</a></p>  # 瞭解便可
            
後端
# 能夠直接用無名分組的狀況
url = reverse('xxx',args=(1,))
# 你也能夠規範寫法
url = reverse('xxx',kwargs={'year':213123})  # 瞭解便可

以編輯功能爲例

url(r'^edit_user/(\d+)/',views.edit_user,name='edit')

def edit_user(request,edit_id):
    # edit_id就是用戶想要編輯數據主鍵值
    pass

{% for user_obj in user_list %}
<a href='/edit_user/{{user_obj.id}}/'>編輯</a>
<a href='{% url 'edit' user_obj.id %}'>編輯</a>
{% endfor %}

路由分發

在django中全部的app均可以有本身獨立的urls.py templates static。
正是因爲上面的特色 你用django開發項目就可以徹底作到多人分組開發 互相不干擾,每一個人只開發本身的app,小組長只須要將全部人開發的app整合到一個空的django項目裏面,而後在settings配置文件註冊 再利用路由分發將多個app整合到一塊兒便可完成大項目的拼接,路由分發解決的就是項目的總路由匹配關係過多的狀況,使用路由分發 會將總路由再也不作匹配的活 而僅僅是作任務分發(請求來了以後 總路由不作對應關係,只詢問你要訪問哪一個app的功能 而後將請求轉發給對應的app去處理)。django

# 第一種分發方式:

# settings中的總路由
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
    url(r'^admin/', admin.site.urls),  # url第一個參數是一個正則表達式
    # 路由分發
    url(r'^app01/',include(app01_urls)),  # 路由分發須要注意的實現 就是總路由裏面不能以$結尾
    url(r'^app02/',include(app02_urls)),
]

# app01的settings中的子路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url('^reg/',views.reg)
]

# app02的settings中的子路由
# app02是剛剛建立的的,要在總路由的INSTALLED_APPS中註冊
from django.conf.urls import url
from app02 import views
urlpatterns = [
    url('^reg/',views.reg)
]
# 第二種分發方式:

最省事的寫法(******)
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))

名稱空間

當多個app中出現了起別名衝突的狀況 你在作路由分發的時候 能夠給每個app建立一個名稱空間,而後在反向解析的時候 能夠選擇到底去哪一個名稱空間中查找別名。bootstrap

url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
            
# 後端
print(reverse('app01:reg'))
print(reverse('app02:reg'))
# 前端
<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>
    
其實上面的名稱空間知識點能夠徹底不用 你只須要保證起別名的時候 在整個django項目中不衝突便可
參考建議
起別名的時候統一加上應用名前綴
urlpatterns = [
    url(r'^reg/',views.reg,name='app02_reg')
]

urlpatterns = [
    url('^reg/',views.reg,name='app01_reg')
]

僞靜態

將一個動態網頁假裝成一個靜態網頁 以此來提升搜索引擎SEO查詢頻率和蒐藏力度
所謂的搜索引擎其實就是一個也別巨大的爬蟲程序後端

虛擬環境

給每個項目 裝備該項目所須要的模塊 不須要的模塊一律不裝
每建立一個虛擬環境就相似於你從新下載了一個純淨python解釋器
以後該項目用到上面 你就裝什麼(虛擬環境一臺機器上能夠有N多個)

不要在你的機器上無限制建立虛擬環境

django 版本區別

django1.X  django2.X

urls.py中路由匹配的方法有區別
django2.X用的是path
urlpatterns = [
    path('admin/', admin.site.urls),
]
django1.X用的是url
urlpatterns = [
    url(r'^reg.html',views.reg,name='app02_reg')
]

# 區別 django2.X裏面path第一個參數不是正則也不支持正則 寫什麼就匹配什麼
# 雖然path不支持正則 感受也好用 django2.X還有一個re_path的方法 該方法就是你django1.X裏面url;
# 雖然path支持 可是它提供了五種轉換器  可以將匹配到的數據自動轉換成對應的類型
# 除了有默認五種轉換器以外 還支持你自定義轉換器

form表單上傳文件,後端如何獲取文件

form表單上傳文件 後端如何獲取文件
form表達傳文件須要注意的事項
    1.method必須改爲post
    2.enctype該成formdata格式
前期你在使用post朝後端發請求的時候 須要去settings配置文件中註釋掉一箇中間件csrf
#urls.py文件
urlpatterns = [
    url('^reg/',views.reg,name='reg'),
    url('^upload_file/',views.upload_file),
]


# upload_file.py文件
def upload_file(request):
    if request.method=='POST':
        print(request.POST)  # <QueryDict: {}>
        print(request.FILES)  # django會將文件類型的數據放到request.files裏面
        # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: aaa.xls (application/vnd.ms-excel)>]}>
        file_obj = request.FILES.get('myfile')
        print(file_obj)  # aaa.xls
        print(file_obj.name)  # aaa.xls
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)

    ''' 
    django針對不一樣得數據類型,會幫你解析並放到不一樣得方法中供你調用
    '''
    return render(request,'upload_file.html')
<!--upload_file.html文件-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>

</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <input type="submit">
</form>
</body>
</html>

本日內容總結
下一篇:django視圖層及模板層

相關文章
相關標籤/搜索