1. 程式人生 > >Django之MTV

Django之MTV

url django views

一、簡單演示

返回當前時間

url.py文件內容:

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^timmer/', views.timmer),
]


views.py文件內容:

from django.shortcuts import render,HttpResponse,redirect
def timmer(request):
    import time
    ctime=time.time()
    # return HttpResponse (ctime)          #只能返回字符串
    return render(request,"timmer.html", {"ctime":ctime})     #返回html,這樣就能定義返回的樣式


timmer.html文件內容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>timmer</title>
    < style >
        p{
        color: red;
        }
    </style>
</head>
<body>

{#雙大括號是模板語法,裏面是變量,接受views.py的參數#}
<p>當前時間:{{ ctime }}</p>
</body>
</html>


二、url控制器

1、url的分組

urls.py文件內容:

from django.conf.urls import url,include
from django.contrib import admin
from django.shortcuts import HttpResponse
from app01.views import *
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^timer/$', timer),                                        # timer(request)
    #分組
    url(r'^books_achrive/(\d+)/$', book_detail),              # book_detail(request,3)
    url(r'^books_achrive/(\d+)/(\d+)/$', books_achrive),        # books_achrive(request,2012,12)
    #有名分組books_achrive後面有一個year組和一個month組
    url(r'^books_achrive/(?P<year>\d+)/(?P<month>\d+)/$', books_achrive2), # books_achrive(request,year=2012,month=12)
]

views.py文件內容:

from django.shortcuts import render,HttpResponse,redirect
def book_detail(reqeust,id):
    return HttpResponse(id)
    
def books_achrive(request,year,month):
    return HttpResponse(year+":"+month)
    
def books_achrive2(request,month,year):
    return HttpResponse(year+":"+month)


這樣用戶訪問的路徑為/books_achrive/2012/12/時,就會在URL匹配到url(r'^books_achrive/(\d+)/(\d+)/$', books_achrive),然後執行books_achrive函數

2、url的分發


在項目下的urls.py文件裏面定義連接到具體的應用的路徑

url(r'^app01/', include('app01.urls'), ),

然後在具體應用的urls.py文件裏面定義具體的url

from django.conf.urls import url,include
from app01.views import *
urlpatterns = [
    url(r'^timer/$', timer), # timer(request)
    url(r'^books_achrive/(\d+)/$', book_detail), # book_detail(request,3)
    url(r'^books_achrive/(?P<year>\d+)/(?P<month>\d+)/$', books_achrive2), # books_achrive(request,year=2012,month=12)
]


3、URL 的反向解析


在使用Django 項目時,一個常見的需求是獲得URL 的最終形式,以用於嵌入到生成的內容中(視圖中和顯示給用戶的URL等)或者用於處理服務器端的導航(重定向等)。

人們強烈希望不要硬編碼這些URL(費力、不可擴展且容易產生錯誤)或者設計一種與URLconf 毫不相關的專門的URL 生成機制,因為這樣容易導致一定程度上產生過期的URL。

換句話講,需要的是一個DRY 機制。除了其它有點,它還允許設計的URL 可以自動更新而不用遍歷項目的源代碼來搜索並替換過期的URL。


在需要URL 的地方,對於不同層級,Django 提供不同的工具用於URL 反查:

(1)在模板中:使用url 模板標簽。

from django.conf.urls import url
from . import views
urlpatterns = [
        url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
]

在模板的代碼中使用下面的方法獲得它們:

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>

(2)在Python 代碼中:使用django.core.urlresolvers.reverse() 函數。

from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
    year = 2006.
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))


(3)在更高層的與處理Django 模型實例相關的代碼中:使用get_absolute_url() 方法。


4、反向解析示例:登錄頁面

urls.py文件內容:

from django.conf.urls import url,include
from django.contrib import admin
from django.shortcuts import render,HttpResponse,redirect
from app01.views import *

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', login,name="xxx"),     #定義url的別名xxx
]

views.py文件內容:

from django.shortcuts import render,HttpResponse,redirect

def login(request):
    if request.method=="GET":
        print(request.GET)
        print(request.POST)
        print(request.method)
        print(request.path)
        print(request.path_info)
        print(request.body)
        return render(request, "login.html")
    else:
        user=request.POST.get("user")
        pwd=request.POST.get("pwd")
        
        if 1:                                    #用戶輸入的用戶名和密碼與數據庫裏面的做對比,判斷是否一致
            return redirect("/app01/timer/")

登錄頁面login.html文件內容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        p{
            color: red;
        }
    </style>
</head>
<body>

<form action="{% url 'xxx' %}" method="post">
    {% csrf_token %}                                  #解決出現Forbidden (403)錯誤
    <p>用戶名 <input type="text" name="user"></p>
    <p>密碼 <input type="password" name="pwd"></p>
    <input type="submit">
</form>

</body>
</html>

利用反向解析的好處:訪問的時候用url的別名可以避免了隨著url的變化而訪問路徑跟著變化


三、視圖層之視圖函數(views)

1、HttpRequest對象的屬性

(1)HttpRequest.body

  一個字符串,代表請求報文的主體。在處理非 HTTP 形式的報文時非常有用,例如:二進制圖片、XML,Json等。

  但是,如果要處理表單數據的時候,推薦還是使用 HttpRequest.POST 。

(2)HttpRequest.path

  一個字符串,表示請求的路徑組件(不含域名)。

  例如:"/music/bands/the_beatles/"

(3)HttpRequest.method

  一個字符串,表示請求使用的HTTP方法。必須使用大寫。

  例如:"GET"、"POST"

(4)HttpRequest.encoding

  一個字符串,表示提交的數據的編碼方式(如果為None則表示使用DEFAULT_CHARSET的設置,默認為'utf-8')。

這個屬性是可寫的,你可以修改它來修改訪問表單數據使用的編碼。

接下來對屬性的任何訪問(例如從GET或POST中讀取數據)將使用新的encoding值。

如果你知道表單數據的編碼不是DEFAULT_CHARSET ,則使用它。


(5)HttpRequest.GET

  一個類似於字典的對象,包含HTTP、GET的所有參數。詳情請參考QueryDict對象。


(6)HttpRequest.POST

  一個類似於字典的對象,如果請求中包含表單數據,則將這些數據封裝成QueryDict對象。

  POST請求可以帶有空的POST字典 —— 如果通過HTTPPOST方法發送一個表單,但是表單中沒有任何的數據,QueryDict對象依然會被建。

因此,不應該使用 if request.POST來檢查使用的是否是POST方法;應該使用 if request.method == "POST"

  另外:如果使用POST上傳文件的話,文件信息將包含在FILES屬性中。


(7)HttpRequest.REQUEST

  一個類似於字典的對象,它首先搜索POST,然後搜索GET,主要是為了方便。靈感來自於PHP的 $_REQUEST。

  例如,如果GET = {"name": "john"}而POST = {"age": '34'} , REQUEST["name"]將等於"john", REQUEST["age"]將等於"34"。

  強烈建議使用GET和POST而不要用REQUEST,因為它們更加明確。


(8)HttpRequest.COOKIES

  一個標準的Python字典,包含所有的cookie。鍵和值都為字符串。


(9)HttpRequest.FILES

  一個類似於字典的對象,包含所有的上傳文件信息。

FILES 中的每個鍵為<input type="file" name="" /> 中的name,值則為對應的數據。


  註意,FILES 只有在請求的方法為POST 且提交的<form> 帶有enctype="multipart/form-data" 的情況下才會包含數據。否則,FILES 將為一個空的類似於字典的對象。

(10)HttpRequest.META

  一個標準的Python 字典,包含所有的HTTP 首部。具體的頭部信息取決於客戶端和服務器,下面是一些示例:


CONTENT_LENGTH —— 請求的正文的長度(是一個字符串)。

CONTENT_TYPE —— 請求的正文的MIME 類型。

HTTP_ACCEPT —— 響應可接收的Content-Type。

HTTP_ACCEPT_ENCODING —— 響應可接收的編碼。

HTTP_ACCEPT_LANGUAGE —— 響應可接收的語言。

HTTP_HOST —— 客服端發送的HTTP Host 頭部。

HTTP_REFERER —— Referring 頁面。

HTTP_USER_AGENT —— 客戶端的user-agent 字符串。

QUERY_STRING —— 單個字符串形式的查詢字符串(未解析過的形式)。

REMOTE_ADDR —— 客戶端的IP 地址。

REMOTE_HOST —— 客戶端的主機名。

REMOTE_USER —— 服務器認證後的用戶。

REQUEST_METHOD —— 一個字符串,例如"GET" 或"POST"。

SERVER_NAME —— 服務器的主機名。

SERVER_PORT —— 服務器的端口(是一個字符串)。

  從上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,請求中的任何 HTTP 首部轉換為 META 的鍵時,

都會將所有字母大寫並將連接符替換為下劃線最後加上 HTTP_ 前綴。

所以,一個叫做 X-Bender 的頭部將轉換成 META 中的 HTTP_X_BENDER 鍵。


(11)HttpRequest.user

  一個AUTH_USER_MODEL類型的對象,表示當前登錄的用戶。

  如果用戶當前沒有登錄,user將設置為django.contrib.auth.models.AnonymousUser的一個實例。你可以通過is_authenticated()區分它們。


例如:

if request.user.is_authenticated():
# Do something for logged-in users.
else:
    # Do something for anonymous users.

  

user 只有當Django啟用AuthenticationMiddleware中間件時才可用。


(12)HttpRequest.session

  一個既可讀又可寫的類似於字典的對象,表示當前的會話。只有當Django啟用會話的支持時才可用。


(13)HttpRequest.resolver_match

  一個ResolverMatch的實例,表示解析後的URL。這個屬性只有在URL解析方法之後才設置,這意味著它在所有的視圖中可以訪問,

但是在URL解析發生之前執行的中間件方法中不可以訪問(比如process_request,但你可以使用process_view代替)。


四、MTV模型

Django的MTV分別代表:

Model(模型):負責業務對象與數據庫的對象(ORM)

Template(模版):負責如何把頁面展示給用戶

View(視圖):負責業務邏輯,並在適當的時候調用Model和Template

此外,Django還有一個urls分發器,它的作用是將一個個URL的頁面請求分發給不同的view處理,view再調用相應的Model和Template


1、模板層(template)

from django.conf.urls import url,include
from django.contrib import admin
from django.shortcuts import HttpResponse
from app01.views import *

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^template/', temp_func,),
]

views.py文件內容:

def temp_func(request):

    l=[11,222,333]
    dic={"name":"yuan","age":23}
    
    class Person(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def learning(self):
             return "learning"
    alex=Person("alex",45)
    egon=Person("egon",36)
    person_list=[alex,egon]
    
    import datetime
    now=datetime.datetime.now()
    print(now)
    
    file_size=234212123
    content="hello yuan world text"
    s="<a href='http://www.baidu.com'>hello</a>"
    #return render(request,"temp.html",{"l":l,"dic":dic})
    return render(request,"temp.html",locals())

app01應用下創建templatetags模塊(文件夾),裏面創建my_filters_tags.py文件,內容如下:

@register.filter
def multi_filter(x,y):
    return x * y
@register.simple_tag
def multi_tag(x,y):
    return x * y

temp.html文件內容:

{% load my_filters_tags %}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h3>變量</h3>
<p>{{ l }}</p>                             {#  結果是:[11, 222, 333]    #}
<p>{{ l.1 }}</p>                           {#  結果是:222   #}
<p>{{ dic }}</p>                            {#  結果是:{'name': 'yuan', 'age': 23}   #}
<p>{{ dic.name }}</p>                       {#  結果是:yuan   #}
<p>{{ alex.age }}</p>                       {#  結果是:45   #}


<h3>過濾器</h3>                           {#  語法;{{obj|filter__name:param}}   #}
<p>{{ l.1|add:100 }}</p>                     {#  結果是:322   #}
<p>{{ now|date:"Y-m-d" }}</p>                 {#  結果是:2018-04-16   #}
<p>{{ file_size|filesizeformat }}</p>           {#  結果是:223.4 MB   #}
<p>{{ content|truncatechars:12 }}</p>           {#  結果是:hello yua...  加上點號一共顯示12個字符 #}
<p>{{ content|truncatewords:2 }}</p>            {#  結果是:hello yuan ...  顯示兩個單詞#}
<p>{{ content|slice:"2:-1" }}</p>              {#  結果是:llo yuan world tex  #}
<p>{{ s|safe }}</p>                        {#  結果是:hello   告訴Django這段代碼是安全的不必轉義#}


<h3>標簽</h3>
{% for person in person_list %}                {#  for循環person_list列表   #}
   <p>{{ forloop.counter0 }} {{ person.name }}:{{ person.age }} --- {{ person.learning }}</p>
{% endfor %}
{#  {{ forloop.counter0 }} 可以取到循環序號  #}

{#  如果變量l.0 > 100,就顯示100,否則顯示變量l.0    #}
{% if l.0 > 100 %}
    <p>100</p>
 {% else %}
    <p>{{ l.0 }}</p>
{% endif %}


<h4>自定義過濾器或者標簽</h4>
{{ l.0|multi_filter:2 }}                          {#  結果是:22   #}
{% multi_tag l.0|add:12 10 %}                     {#  結果是:230   #}
</body>
</html>

五、Django-model基礎


1、在settings.py配置下面內容可以查看翻譯成的sql語句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
} 

2、創建模型

class Author(models.Model):                            #Author表包含 nid、name、age、 authorDetail字段
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    # 與AuthorDetail建立一對一的關系
    authorDetail = models.OneToOneField(to="AuthorDetail")
    
class AuthorDetail(models.Model):                        #AuthorDetail表包含nid、birthday、telephone、addr字段
    nid = models.AutoField(primary_key=True)
    birthday = models.DateField()
    telephone = models.BigIntegerField()
    addr = models.CharField(max_length=64)
    
class Publish(models.Model):                             #Publish表包含nid、name、city、email字段
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()
    
class Book(models.Model):                               #Book表包含nid、title、publishDate、price、keepNum、publish字段
    nid = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    publishDate = models.DateField()
    price = models.DecimalField(max_digits=5, decimal_places=2)
    keepNum = models.IntegerField() < br > commentNum = models.IntegerField()
    # 與Publish建立一對多的關系,外鍵字段建立在多的一方
    publish = models.ForeignKey(to="Publish", to_field="nid")
    # 與Author表建立多對多的關系,ManyToManyField可以建在兩個模型中的任意一個,自動創建第三張表
    authors = models.ManyToManyField(to='Author') 

3、字段選項

(1)null

如果為True,Django將用NULL來在數據庫中存儲空值。 默認值是False.

(2)blank

如果為True,該字段允許不填。默認為False。要註意,這與null不同。null純粹是數據庫範疇的,而blank是數據驗證範疇的。

如果一個字段的blank = True,表單的驗證將允許該字段是空值。如果字段的blank = False,該字段就是必填的。

(3)default

字段的默認值。可以是一個值或者可調用對象。如果可調用 ,每有新對象被創建它都會被調用。

(4)primary_key

如果為True,那麽這個字段就是模型的主鍵。如果你沒有指定任何一個字段的primary_key = True,Django就會自動添加一個IntegerField字段做為主鍵,所以除非你想覆蓋默認的主鍵行為,否則沒必要設置任何一個字段的primary_key = True。

(5)unique

如果該值設置為True, 這個數據字段的值在整張表中必須是唯一的

(6)choices

由二元組組成的一個可叠代對象(例如,列表或元組),用來給字段提供選擇項。 如果設置了choices ,默認的表單將是一個選擇框而不是標準的文本框,而且這個選擇框的選項就是choices 中的選項。


4、添加表記錄

(1)普通字段

    #1、方式1
    publish_obj = Publish(name="人民出版社", city="北京", email="[email protected]")
    publish_obj.save()  # 將數據保存到數據庫
    #2、方式2 < br > 返回值publish_obj是添加的記錄對象
    publish_obj = Publish.objects.create(name="人民出版社", city="北京",
                                         email="[email protected]") < br > < br > 方式3 < br > 表.objects.create(**request.POST.dict())

(2)外鍵字段

    #1、方式1:
    publish_obj = Publish.objects.get(nid=1)
    Book.objects.create(title="西遊記", publishDate="2012-12-12", price=665, pageNum=334, publish=publish_obj)
    #2、方式2:
    Book.objects.create(title="西遊記", publishDate="2012-12-12", price=665, pageNum=334, publish_id=1) 

(3)多對多字段

    book_obj = Book.objects.create(title="追風箏的人", publishDate="2012-11-12", price=69, pageNum=314, publish_id=1)
    author_yuan = Author.objects.create(name="yuan", age=23, authorDetail_id=1)
    author_egon = Author.objects.create(name="egon", age=32, authorDetail_id=2)
    book_obj.authors.add(author_egon, author_yuan)  # 將某個特定的 model 對象添加到被關聯對象集合中。   =======    book_obj.authors.add(*[])
    book_obj.authors.create()  # 創建並保存一個新對象,然後將這個對象加被關聯對象的集合中,然後返回這個新對象。
    
解除關系:
    book_obj.authors.remove()     # 將某個特定的對象從被關聯對象集合中去除。    ======   book_obj.authors.remove(*[])
    book_obj.authors.clear()       #清空被關聯對象集合。

5、查詢表記錄

(1)查詢相關API

< 1 > all(): 查詢所有結果

< 2 > filter(**kwargs): 它包含了與所給篩選條件相匹配的對象

< 3 > get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。

< 4 > exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象

< 5 > values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後得到的並不是一系列model的實例化對象,而是一個可叠代的字典序列

< 6 > values_list(*field): 它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列

< 7 > order_by(*field): 對查詢結果排序

< 8 > reverse(): 對查詢結果反向排序

< 9 > distinct(): 從返回結果中剔除重復紀錄

< 10 > count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。

< 11 > first(): 返回第一條記錄

< 12 > last(): 返回最後一條記錄

< 13 > exists(): 如果QuerySet包含數據,就返回True,否則返回False


(2)雙下劃線之單表查詢

models.Tb1.objects.filter(id__lt=10, id__gt=1)       # 獲取id大於1 且 小於10的值
models.Tb1.objects.filter(id__in=[11, 22, 33])      # 獲取id等於11、22、33的數據
models.Tb1.objects.exclude(id__in=[11, 22, 33])     # not in
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven")   # icontains大小寫不敏感
models.Tb1.objects.filter(id__range=[1, 2])         # 範圍bettwen and

startswith,istartswith, endswith, iendswith 

(3)基於對象的跨表查詢

< 1 >一對多查詢(Publish 與 Book)

正向查詢(按字段:publish):
# 查詢nid=1的書籍的出版社所在的城市<br>
book_obj=Book.objects.get(nid=1)<br>print(book_obj.publish.city) # book_obj.publish 是nid=1的書籍對象關聯的出版社對象
 
反向查詢(按表名:book_set):
# 查詢 人民出版社出版過的所有書籍
publish = Publish.objects.get(name="人民出版社")
book_list = publish.book_set.all()          # 與人民出版社關聯的所有書籍對象集合
for book_obj in book_list:
    print(book_obj.title)

< 2 >一對一查詢

正向查詢(按字段:authorDetail):
# 查詢egon作者的手機號
author_egon = Author.objects.get(name="egon")
print(author_egon.authorDetail.telephone)

反向查詢(按表名:author):
# 查詢所有住址在北京的作者的姓名
authorDetail_list = AuthorDetail.objects.filter(addr="beijing")
for obj in authorDetail_list:
    print(obj.author.name)

< 3 >多對多查詢

正向查詢(按字段:authors):
book_obj = Book.objects.filter(title="西遊記").first()
authors = book_obj.authors.all()
for author_obj in authors:
    print(author_obj.name, author_obj.authorDetail.telephone)
    
反向查詢(按表名:book_set):
# 查詢egon出過的所有書籍的名字
author_obj = Author.objects.get(name="egon")
book_list = author_obj.book_set.all()       # 與egon作者相關的所有書籍
for book_obj in book_list:
    print(book_obj.title)
    
    
#查詢 人民出版社出版過的所有書籍
publish = Publish.objects.get(name="人民出版社")
book_list = publish.bookList.all()          # 與人民出版社關聯的所有書籍對象集合

(4)基於雙下劃線的跨表查詢

# 練習1: 查詢人民出版社出版過的所有書籍的名字與價格(一對多)

    # 正向查詢 按字段:publish
    queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","price")
    
    # 反向查詢 按表名:book
    queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__price")

# 練習2: 查詢egon出過的所有書籍的名字(多對多)

    # 正向查詢 按字段:authors:
    queryResult=Book.objects.filter(authors__name="yuan").values_list("title")
    
    # 反向查詢 按表名:book
    queryResult=Author.objects.filter(name="yuan").values_list("book__title","book__price")

# 練習3: 查詢人民出版社出版過的所有書籍的名字以及作者的姓名

    # 正向查詢
    queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")
    
    # 反向查詢
    queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")

# 練習4: 手機號以151開頭的作者出版過的所有書籍名稱以及出版社名稱

    queryResult=Book.objects.filter(authors__authorDetail__telephone__regex="151").values_list("title","publish__name")

# 練習1: 查詢人民出版社出版過的所有書籍的名字與價格(一對多)

# 反向查詢 不再按表名:book,而是related_name:bookList
    queryResult = Publish.objects.filter(name="人民出版社").values_list("bookList__title", "bookList__price")

6、修改表記錄

Book.objects.filter(price=123,title="python").update(title="python123")

7、刪除表記錄

Book.objects.filter(price=123,title="python").delete()
你也可以一次性刪除多個對象。每個 QuerySet 都有一個 delete() 方法,它一次性刪除 QuerySet 中所有的對象。

例如,下面的代碼將刪除 pub_date 是2005年的 Entry 對象:
Entry.objects.filter(pub_date__year=2005).delete()

要牢記這一點:無論在什麽情況下,QuerySet 中的 delete() 方法都只使用一條 SQL 語句一次性刪除所有對象,而並不是分別刪除每個對象。如果你想使用在 model 中自定義的 delete() 方法,就要自行調用每個對象的delete 方法。(例如,遍歷 QuerySet,在每個對象上調用 delete()方法),而不是使用 QuerySet 中的delete()方法。


在 Django 刪除對象時,會模仿 SQL 約束 ON DELETE CASCADE 的行為,換句話說,刪除一個對象時也會刪除與它相關聯的外鍵對象。
例如:
b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()





Django之MTV