Django知識總結

1、什麼是web框架?

  框架,即framework,特指爲解決一個開放性問題而設計的具備必定約束性的支撐結構,使用框架能夠幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來作表演。css

  web應用  訪問請求流程html

  

  1. *瀏覽器發送一個HTTP請求;
  2. *服務器收到請求,生成一個HTML文檔(待補充;是不是所有類型的訪問都須要生成文檔);
  3. *服務器把HTML文檔做爲HTTP響應的Body發送給瀏覽器;
  4. *瀏覽器收到HTTP響應,從HTTP Body取出HTML文檔並解析顯示

  對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。(即BS架構)前端

  靜態頁面--最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。python

  若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。mysql

  這個接口就是WSGI:Web Server Gateway Interface。
  
jquery

  WSGI 簡單介紹

  WSGI,全稱 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是爲 Python 語言定義的 Web 服務器和 Web 應用程序或框架之間的一種簡單而通用的接口。自從 WSGI 被開發出來之後,許多其它語言中也出現了相似接口。nginx

  WSGI 是做爲 Web 服務器與 Web 應用程序或應用框架之間的一種低級別的,以提高可移植 Web 應用開發的共同點。WSGI 是基於現存的 CGI 標準而設計的。web

  不少框架都自帶了 WSGI server ,好比 Flask,webpy,Django、CherryPy等等。固然性能都很差,自帶的 web server 更多的是測試用途,發佈時則使用生產環境的 WSGI server或者是聯合 nginx 作 uwsgi。ajax

  通俗來說,WSGI就像是一座橋樑,一邊連着web服務器,另外一邊連着用戶的應用。可是呢,這個橋的功能很弱,有時候還須要別的橋來幫忙才能進行處理。sql

  

  WSGI的做用

  WSGI有兩方:「服務器」或「網關」一方,以及「應用程序」或「應用框架」一方。服務方調用應用方,提供環境信息,以及一個回調函數(提供給應用程序用來將消息頭傳遞給服務器方),並接收Web內容做爲返回值。

  所謂的 WSGI中間件同時實現了API的兩方,所以能夠在WSGI服務和WSGI應用之間起調解做用:從WSGI服務器的角度來講,中間件扮演應用程序,而從應用程序的角度來講,中間件扮演服務器。「中間件」組件能夠執行如下功能:

  • 重寫環境變量後,根據目標URL,將請求消息路由到不一樣的應用對象。
  • 容許在一個進程中同時運行多個應用程序或應用框架。
  • 負載均衡和遠程處理,經過在網絡上轉發請求和響應消息。
  • 進行內容後處理,例如應用XSLT樣式表。

  WSGI 的設計確實參考了 Java 的 servlet。http://www.python.org/dev/peps/pep-0333/ 有這麼一段話:

By contrast, although Java has just as many web application frameworks available, Java’s 「servlet」 API makes it possible for applications written with any Java web application framework to run in any web server that supports the servlet API.

  另外,須要說起的一點是:其它基於python的web框架,如tornado、flask、webpy都是在這個範圍內進行增刪裁剪的。例如tornado用的是本身的異步非阻塞「wsgi」,flask則只提供了最精簡和基本的框架。Django則是直接使用了WSGI,並實現了大部分功能。

WSGI實例一

# -*- coding: utf-8 -*-
from wsgiref.simple_server import make_server
def application(environ, start_response):
  start_response('200 OK',[('Content-Type','text/html')])
return[b'<h1 >Hello, web!</h1>']
#''中間爲空,表示的是本地地址
httpd = make_server('',8080, application)
print('Serving HTTP on port 8000...')
# 開始監聽HTTP請求:
httpd.serve_forever()</pre>

'''
1.整個application()函數自己沒有涉及到任何解析HTTP的部分,也就是說,底層代碼不須要咱們本身編寫,
咱們只負責在更高層次上考慮如何響應請求就能夠了。

2.application()函數必須由WSGI服務器來調用。有不少符合WSGI規範的服務器,咱們能夠挑選一個來用。

3.Python內置了一個WSGI服務器,這個模塊叫wsgiref

4.application()函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:
//environ:一個包含全部HTTP請求信息的dict對象; //start_response:一個發送HTTP響應的函數。

5.在application()函數中,調用:start_response('200 OK',[('Content-Type','text/html')])
就發送了HTTP響應的Header,注意Header只能發送一次,也就是隻能調用一次start_response()函數。
start_response()函數接收兩個參數,一個是HTTP響應碼,一個是一組list表示的HTTP Header,每一個
Header用一個包含兩個str的tuple表示。

6.一般狀況下,都應該把Content-Type頭髮送給瀏覽器。其餘不少經常使用的HTTP Header也應該發送。
而後,函數的返回值b'<h1>Hello, web!</h1>'將做爲HTTP響應的Body發送給瀏覽器。

7.有了WSGI,咱們關心的就是如何從environ這個dict對象拿到HTTP請求信息,而後構造HTML,經過
start_response()發送Header,最後返回Body。
'''
WSGI實例二

from wsgiref.simple_server import make_server
def f1():
    f1=open("jd_index1.html","rb")
    data1=f1.read()
return[data1]
def f2():
    f2=open("tb_index.html","rb")
    data2=f2.read()
return[data2]
def application(environ, start_response):
print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK',[('Content-Type','text/html')])
# 若是URL路徑爲京東,執行函數1,返回京東主頁
if path=="/jingdong":
return f1()
# 若是URL路徑爲淘寶,執行函數2,返回淘寶主頁
elif path=="/taobao":
return f2()
else:
return["<h1>404</h1>".encode("utf8")]
httpd = make_server('',8810, application)
print('Serving HTTP on port 8810...')
# 開始監聽HTTP請求:
httpd.serve_forever()
打開瀏覽器訪問相應的路徑 
這裏咱們WSGI每次修改完數據後,都須要從新啓動該服務。
WSGI實例3 打印當前時間

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016/11/24
# @Author  : Jesson 
import time
from wsgiref.simple_server import make_server
def f1(req):
print(req)
print(req["QUERY_STRING"])
    f1=open("jd_index1.html","rb")
    data1=f1.read()
return[data1]
def f2(req):
  f2=open("tb_index.html","rb")
    data2=f2.read()
return[data2]
def f3(req):#模版以及數據庫
  f3=open("current_time.html","rb")
    data3=f3.read()
    times=time.strftime("%Y-%m-%d %X", time.localtime())
# 在前端相應的頁面 設置自定義模版語言'! !'
  data3=str(data3,"utf8").replace("!time!",str(times))
return[data3.encode("utf8")]
def routers():
  urlpatterns =(
('/jingdong',f1),
('/taobao',f2),
("/cur_time",f3)
)
return urlpatterns
def application(environ, start_response):
print(environ['PATH_INFO'])
    path=environ['PATH_INFO']
    start_response('200 OK',[('Content-Type','text/html')])
    urlpatterns = routers()
    func =None
for item in urlpatterns:
if item[0]== path:
  func = item[1]
break
if func:
return func(environ)
else:
return["<h1>404</h1>".encode("utf8")]
httpd = make_server('',8828, application)
print('Serving HTTP on port 8828...')
# 開始監聽HTTP請求:
httpd.serve_forever()

  MVC和MTV設計模式

  MVC百度百科:全名Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典範,用一種業務邏輯、數據、界面顯示分離的方法組織代碼,將業務邏輯彙集到一個部件裏面,在改進和個性化定製界面及用戶交互的同時,不須要從新編寫業務邏輯。

  通俗解釋:一種文件的組織和管理形式!不要被縮寫嚇到了,這其實就是把不一樣類型的文件放到不一樣的目錄下的一種方法,而後取了個高大上的名字。固然,它帶來的好處有不少,好比先後端分離,鬆耦合等等,就不詳細說明了。

模型(model):定義數據庫相關的內容,通常放在models.py文件中。 
視圖(view):定義HTML等靜態網頁文件相關,也就是那些html、css、js等前端的東西。 
控制器(controller):定義業務邏輯相關,就是你的主要代碼。

  MTV: 有些WEB框架以爲MVC的字面意思很彆扭,就給它改了一下。view再也不是HTML相關,而是主業務邏輯了,至關於控制器。html被放在Templates中,稱做模板,因而MVC就變成了MTV。這其實就是一個文字遊戲,和MVC本質上是同樣的,換了個名字和叫法而已,換湯不換藥。

  Django的MTV模型組織

  在web開發的項目文件中,相關目錄分開存放,必需要有機制將他們在內裏進行耦合。在Django中,urls、orm、static、settings等起着重要的做用。

2、Django

  一、學Django學的是什麼?

  1. 目錄結構規範
  2. urls路由方式
  3. settings配置
  4. ORM操做
  5. 模板渲染
  6. 其它

  二、Django工做流程

  安裝: pip3 install django
  建立project工程:django-admin startproject mysite 
  建立APP應用:python mannage.py startapp  app01 
  settings配置:TEMPLATES
          STATICFILES_DIRS=(os.path.join(BASE_DIR,"statics"),)  #必定要加逗號
          # 咱們只能用 STATIC_URL,但STATIC_URL會按着你的STATICFILES_DIRS去找
  根據需求設計代碼:url.py  view.py
  模版引擎:templates
  鏈接數據庫,操做數據:model.py

  三、Django命令行工具

  django-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每個Django Project裏都會有一個mannage.py。

  manage.py —– Django項目裏面的工具,經過它能夠調用django shell和數據庫等。
  settings.py —- 包含了項目的默認設置,包括數據庫信息,調試標誌以及其餘一些工做的變量。
  urls.py —– 負責把URL模式映射到應用程序。

  在mysite目錄下建立app01應用: python manage.py startapp app01

   

  啓動django項目:python manage.py runserver 8080 

    生成同步數據庫的腳本文件:python manage.py makemigrations 
  
同步數據庫: python manage.py migrate 

  注意:

 

在開發過程當中,數據庫同步誤操做以後,不免會遇到後面不能同步成功的狀況,解決這個問題的一個簡單粗暴方法是把migrations目錄下的腳本(除__init__.py以外)所有刪掉,再把數據庫刪掉以後建立一個新的數據庫,數據庫同步操做再從新作一遍。

  四、Django--admin

  1. 當咱們訪問http://127.0.0.1:8080/admin/時,會出現: 

    因此咱們須要爲進入這個項目的後臺建立超級管理員:python manage.py createsuperuser 終端執行上述命令,設置好用戶名和密碼後即可登陸啦! 
    設置用戶名的時候,郵箱email能夠不用輸入,密碼有複雜度校驗,設置的複雜點。 
    另外,還會提示你,密碼會明文顯示。

    Warning: Password input may be echoed. 
    OK~ 如此優雅的後臺界面! 

  2. 清空數據庫:** python manage.py flush**

  3. 查詢某個命令的詳細信息: django-admin.py help startapp
    admin 是Django 自帶的一個後臺數據庫管理系統。
  4. 啓動交互界面 :pythonmanage.pyshell
    這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據,還有一些小測試很是方便。

   

  如何更改正在運行的開發服務器端口

  1. #進入django命令行,執行:
  2. python manage.py runserver 加上新的端口號8080

  六、Django URL (路由系統)

   

    1.單一路由對應

1
url(r '^index$' , views.index),

    二、基於正則的路由

1
2
url(r '^index/(\d*)' , views.index),
url(r '^manage/(?P<name>\w*)/(?P<id>\d*)' , views.manage),

    三、添加額外的參數

1
url(r '^manage/(?P<name>\w*)' , views.manage,{ 'id' : 333 }),

    四、爲路由映射設置名稱

1
2
url(r '^home' , views.home, name = 'h1' ),
url(r '^index/(\d*)' , views.index, name = 'h2' ),

設置名稱以後,能夠在不一樣的地方調用,如:

  • 模板中使用生成URL     {% url 'h2' 2012 %}
  • 函數中使用生成URL     reverse('h2', args=(2012,))      路徑:django.urls.reverse
  • Model中使用獲取URL  自定義get_absolute_url() 方法  class NewType(models.Model):

 

1
2
3
4
5
6
7
8
9
10
11
12
13
caption  =  models.CharField(max_length = 16 )
 
 
def  get_absolute_url( self ):
     """
     爲每一個對象生成一個URL
     應用:在對象列表中生成查看詳細的URL,使用此方法便可!!!
     :return:
     """
     # return '/%s/%s' % (self._meta.db_table, self.id)
     # 或
     from  django.urls  import  reverse
     return  reverse( 'NewType.Detail' , kwargs = { 'nid' self . id })

 

獲取請求匹配成功的URL信息:request.resolver_match

    五、路由分發

1
url(r '^web/' ,include( 'web.urls' )),

   七、Ajax操做

$.ajax({
            url:'/csrf1.html',                                          #指定路徑
            type:'POST',                                                #什麼方式發送,get,post,put,delete
            headers:{'X-CSRFToken':token},               #請求頭也能夠放東西
            data:{'user':user},                                     #請求體傳的的東西
            dataType:'JSON',                                        #接收來自服務端的json字符串自動解成字符串
            traditional:true,                                           #串列表或元組的時候用
            success:function (arg) {                             #會調函數,參數是服務端返回的字符串
                console.log(arg);
            }
        })                

  八、Bootstrap BootStrap響應式佈局@media  fontawesome

  九、阻止默認事件:

    js阻止默認事件的發生:onclick='return func();'     function down(){return false;}
    jQuery事件阻止默認事件發生:$('#addModal').click(function(){return false;})            

  十、Http請求生命週期:    

    請求頭 -> 提取URL -> 路由關係匹配 -> 函數 (模板+數據渲染) -> 返回用戶(響應頭+響應體)

  十一、redirect:

    重定向是服務端給客戶端發送一個重定向命令,而後客戶端在鏈接到新的地址,重定向是有服務端發起,瀏覽器完成

  十二、render:

    模板渲染也是有服務端模板和要返回給客戶的內容結合後的新的字符串發送給瀏覽器,瀏覽器識別並顯示出來

  1三、母版

      layout.html
      {% block x %}{% endblock %}

     1四、子版

      {% extends 'layout' %}

      {% block x %}.......{% endblock %}

   1五、Cookie

      在瀏覽器上保持的鍵值對,參數(超時時間,域名)

      服務器寫Cookie:
      #obj=HttpReponse(...)
      #obj=render(...)
      obj=redirect(...) #不必定是redirect三個中的任意一個都行
      obj.set_cookie(k1,v1,max_age) #max_age超時時間,過了這個時間就消失了
      obj.set_signed_cookie(k1,v1,max_age,salt='fff') #加鹽版
      獲取Cookie:
      request.COOKIES.get('k1')
      request.get_signed_cookie('k1'.salt='fff') #接收加鹽版Cookie
      Cookie做用登陸和限制操做次數(投票)

   1六、ORM操做

須要修改的地方:
1.將MySQLdb修改成pymysql
2.把SQLlite改成mysql

步驟:

1.建立數據庫
2.DATABASES = {
	'default': {
	'ENGINE': 'django.db.backends.mysql',
	'NAME':'db6',
	'USER': 'root',
	'PASSWORD': '',
	'HOST': 'localhost',
	'PORT': 3306,
	}
  }
3.import pymysql
  pymysql.install_as_MySQLdb()
4.在models中建立:
	class UserInfo(models.Model):
	nid=models.BigAutoField(primary_key=True)
	username=models.CharField(max_length=32)
	password=models.CharField(max_length=64)
5.註冊app01
  INSTALLED_APPS = [
	'django.contrib.admin',
	'django.contrib.auth',
	'django.contrib.contenttypes',
	'django.contrib.sessions',
	'django.contrib.messages',
	'django.contrib.staticfiles',
	'app01'
  ]
6.建立數據表
	Python manage.py makemigrations
	python manage.py migrate

7.class UserGroup(models.Model):
		'''
		部門
		'''
		title=models.CharField(max_length=32)

  class UserInfo(models.Model):
		'''
		員工
		'''
		nid=models.BigAutoField(primary_key=True)   #AutoField 自動字段,這裏是自增字段至關於自增int類型
		user=models.CharField(max_length=32)
		password=models.CharField(max_length=64)
		# age=models.IntegerField(null=True)
		age=models.IntegerField(default=1)
		ug=models.ForeignKey("UserGroup",null=True)
8.連表正反向操做

#兩張表userinfo(含外鍵列ut_id)和usertype
#對象正向操做: ut.(usertype列名)
#對象反向操做:userinfo_set.(userinfo列名)
value正向操做:ut__(usertype列名)
value反向操做:userinfo__(userinfo列名)

 九、更多操作

  http://www.cnblogs.com/wupeiqi/articles/6216618.html

  1七、分頁

  1八、xss攻擊

  

 

  1九、CSRF

  

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/csrf1.html" method="POST">
//方式一***********************************************
{#        {% csrf_token %}#}
        <input type="text" name="user" id="user">
        <input type="submit" value="提交">
        <button onclick="submitForm()">Ajax提交</button>
    </form>

</body>
<script src="/static/jquery-3.2.1.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
//方式二***********************************************
{#    function submitForm() {#}
{#        var csrf = $('input[name="csrfmiddlewaretoken"]').val();#}
{#        var user = $('#user').val();#}
{#        $.ajax({#}
{#            url:'/csrf1.html',#}
{#            type:'POST',#}
{#            data:{'user':user,'csrfmiddlewaretoken':csrf},#}
{#            success:function (arg) {#}
{#                console.log(arg);#}
{#            }#}
{#        })#}
{#    }#}
//方式三***********************************************
    function submitForm() {
        var token=$.cookie('csrftoken');
        var user=$('#user').val();
        $.ajax({
            url:'/csrf1.html',
            type:'POST',
            headers:{'X-CSRFToken':token},
            data:{'user':user},
            dataType:'JSON',
            traditional:true,
            success:function (arg) {
                console.log(arg);
            }
        })
    }
//方式四************************************************
    function submitForm(){
        $.ajax({
            url:'/csrf1.html',
            type:'POST',
            data:{'user':user,'csrfmiddlewaretoken':"{{csrf_token}}"}
            dataType:'JSON',
            traditional:true,
            success:function (arg) {
                consol.log(arg);
            }
        })
    }
</script>
</html>




1. CSRF
a. 基本應用
form表單中添加
{% csrf_token %}

b. 全站禁用
# 'django.middleware.csrf.CsrfViewMiddleware',

c. 局部禁用
'django.middleware.csrf.CsrfViewMiddleware',

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def csrf1(request):

if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')
d. 局部使用
# 'django.middleware.csrf.CsrfViewMiddleware',

from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_protect
def csrf1(request):

if request.method == 'GET':
return render(request,'csrf1.html')
else:
return HttpResponse('ok')

c. 特殊CBV
from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(csrf_protect,name='dispatch')
class Foo(View):

def get(self,request):
pass

def post(self,request):
pass

PS:CBV中添加裝飾器
def wrapper(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
# 1. 指定方法上添加裝飾器

# class Foo(View):
#
# @method_decorator(wrapper)
# def get(self,request):
# pass
#
# def post(self,request):
# pass
# 2. 在類上添加
# @method_decorator(wrapper,name='dispatch')
# class Foo(View):
#
# def get(self,request):
# pass
#
# def post(self,request):
# pass


Ajax提交數據時候,攜帶CSRF:
a. 放置在data中攜帶

<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script>
function submitForm(){
var csrf = $('input[name="csrfmiddlewaretoken"]').val();
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
data: { "user":user,'csrfmiddlewaretoken': csrf},
success:function(arg){
console.log(arg);
}
})
}

</script>

b. 放在請求頭中

<form method="POST" action="/csrf1.html">
{% csrf_token %}
<input id="user" type="text" name="user" />
<input type="submit" value="提交"/>
<a onclick="submitForm();">Ajax提交</a>
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>

<script>
function submitForm(){
var token = $.cookie('csrftoken');
var user = $('#user').val();
$.ajax({
url: '/csrf1.html',
type: 'POST',
headers:{'X-CSRFToken': token},
data: { "user":user},
success:function(arg){
console.log(arg);
}
})
}
</script>

  20、include

導入小組件
pub.html
    <div>
        <h3>特別漂亮的組件</h3>
        <div class="title">標題:{{ name }}</div>
        <div class="content">內容:{{ name }}</div>
    </div>
*********************************************************************
test.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    {% include 'pub.html' %}
    {% include 'pub.html' %}
    {% include 'pub.html' %}
</body>
</html>        

  2一、函數

函數-> 自動執行
模板自定義函數:
    - simple_filter
        - 最多兩個參數,方式: {{第一個參數|函數名稱:"第二個參數"}}
        - 能夠作條件判斷
    - simple_tag
        - 無限制: {% 函數名 參數 參數%}

  2二、Session

    定義:保存在服務端的數據(本質是鍵值對)
    應用:依賴cookie
    做用:保持會話(Web網站)
    好處:敏感信息不會直接給客戶端

  2三、自關聯

class UInfo(models.Model):
    nickname=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=64)
    gender_choices=[
        (1,''),
        (2,''),
    ]
    gender=models.IntegerField(choices=gender_choices)
    m=models.ManyToManyField('UInfo')

'''
Reverse accessor for 'U2U.b' clashes with reverse accessor for 'U2U.g'.
'UInfo.b'的反向訪問器與「UInfo.g」的反向訪問器衝突,
obj(對象男).U2U_set.all()與obj(對象女).U2U_set.all()同樣產生衝突
related_qury_name:[a,b]
    obj(對象男).a_set.all()
    obj(對象女).b_set.all()
related_name:[a,b]
    obj(對象男).a.all()
    obj(對象女).b.all()
'''
# class U2U(models.Model):
#     g=models.ForeignKey('UInfo',related_name='boys')
#     b=models.ForeignKey('UInfo',related_name='girls')

class Comment(models.Model):
    new_id=models.IntegerField()            #新聞ID
    content=models.CharField(max_length=32) #評論內容
    user=models.CharField(max_length=32)    #評論者
    reply=models.ForeignKey('Comment',null=True,blank=True)
自關聯models
def test2(request):
#多對多兩張表自關聯
    # #主流方式一,傳id
    # models.U2U.objects.create(b_id=1,g_id=4)
    # models.U2U.objects.create(b_id=1,g_id=5)
    # models.U2U.objects.create(b_id=1,g_id=6)
    # models.U2U.objects.create(b_id=2,g_id=5)
    # models.U2U.objects.create(b_id=3,g_id=6)
    # #主流方式二,傳對象
    # boy=models.UInfo.objects.filter(gender=1,id=2).first()
    # girl=models.UInfo.objects.first(gender=2,id=6).first()
    # models.U2U.objects.create(b=boy,g=girl)
    # #雖然穿的是對象可是其內部本質也是取的id
    # xz=models.UInfo.objects.filter(id=1).first()
    # ret=xz.girls.all() #和xz對象(行)有關係的U2U表中的全部對象(行)
    # print(ret)
    # for u in ret:
    #     print(u.g.nickname) #從U2U跨表到UInfo

#多對多ManyToMany自關聯,from屬於正向操做,to屬於反向操做
    #from正向操做
    # xz=models.UInfo.objects.filter(id=1).first()
    # objs=xz.m.all()
    # # print(objs)
    # for obj in objs:
    #     print(obj.nickname)
    #to反向操做
    # mr=models.UInfo.objects.filter(id=4).first()
    # print(mr.nickname)
    # v=mr.uinfo_set.all()
    # for row in v:
    #     print(row.nickname)

#FK自關聯
    # obj=models.Comment.objects.filter(id=4).first() #對象(第四行)
    # print(obj.reply) #對象(與第四行相關聯的那行)
    return HttpResponse('...')
自關聯views
相關文章
相關標籤/搜索