久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

Python自動化開發(fā)學習25-Django

組合搜索

下面要講的是基于模板語言的實現(xiàn)方法,完全沒有使用js。講的時候有點混亂,把其他與效果實現(xiàn)無關的小知識點也順帶講了一下。不過我最后做了小結。

玉樹網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、成都響應式網(wǎng)站建設等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)建站成立于2013年到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選創(chuàng)新互聯(lián)建站。

準備表結構

這里講組合搜索,所以要2個搜索條件。這里用一個選項保存在內(nèi)存中的type和一個保存在數(shù)據(jù)庫中的section:

# models.py 文件中的表結構
class Article(models.Model):
    """文章信息"""
    title = models.CharField(verbose_name="文章標題", max_length=128)
    create_time = models.DateTimeField(verbose_name="創(chuàng)建時間", auto_now_add=True)
    author = models.ForeignKey('UserInfo', models.CASCADE, related_name='author', verbose_name="作者")
    section = models.ForeignKey('Section', models.CASCADE, verbose_name="所屬板塊")
    type_choices = [(1, "原創(chuàng)"), (2, "轉(zhuǎn)載"), (3, "翻譯")]
    type = models.IntegerField(choices=type_choices, verbose_name="文章類型")

class Section(models.Model):
    """文章所屬的板塊"""
    name = models.CharField(verbose_name="板塊", max_length=32)

    def __str__(self):
        return self.name

動態(tài)的根據(jù)url處理篩選

urls里使用捕獲參數(shù)的方法,這里的名字不能隨便取,要取一個和數(shù)據(jù)庫表的字段名一樣的名字:

path('search-<int:section>-<int:type>/', views.Search.as_view()),

因為這里字典的key就是字段名,這樣處理函數(shù)里就可以直接使用**kwargs來篩選了:

def search(request, **kwargs):
    article_obj = models.Article.objects.filter(**kwargs)

這里還有個問題,一般搜索的條件會有一個全部。這里可以用0來表示全部,因為數(shù)據(jù)庫的id是從1開始的。但是這樣的話按照上面的代碼,將什么也搜索不到。這條命令可以搜索到全部的數(shù)據(jù):

article_obj = models.Article.objects.filter(**{})  # 就是空字典,相當于就是.all()

最終寫成下面這樣來實現(xiàn):

def search(request, **kwargs):
    condition = {}
    for k, v in kwargs.items():
        if v == 0:
            pass
        else:
            condition[k] = v
    article_obj = models.Article.objects.filter(**condition).order_by('-id')
    types = models.Article.type_choices
    section_obj = models.Section.objects.all()
    return render(request, 'search.html', {'article_obj': article_obj, 'types': types, 'section_obj': section_obj})

上面的實現(xiàn)的好處是,處理函數(shù)里對于搜索條件沒有寫死。urls直接和數(shù)據(jù)庫的字典名對應,之后如果要增減或者修改搜索條件,處理函數(shù)也不用做修改。

生成url的方法

上面只解決了通過url來獲取到篩選的數(shù)據(jù),但是首先得有url。如果是單個的篩選條件,那么一個a標簽就能解決問題:

<a href="detail-{{ row.id }}"></a>

但是對于多個篩選條件的組合搜索,另外一個值就無法動態(tài)的保留了。
獲取當前url的方法
先給url加個名字

path('detail-<int:hid>-<int:uid>.html', views.detail, name='detail'),

下面的2個方法都可以在處理函數(shù)里獲取到當前的url:

print(request.path_info)
from django.urls import reverse
url = reverse('detail', kwargs=kwargs)
print(url)
# reverse是生成url,如果傳入一個別的字典,就能動態(tài)的生成url
url = reverse('detail', kwargs={'hid': '1', 'uid': '2'})
print(url)

所以url的信息全部在kwargs里了,把這個kwargs也傳給前端:

def search(request, **kwargs):
    # print(kwargs)
    # print(reverse('search', args=kwargs.values()))
    condition = {}
    for k, v in kwargs.items():
        if v == 0:
            pass
        else:
            condition[k] = v
    # print(condition)
    article_obj = models.Article.objects.filter(**condition).order_by('-id')
    types = models.Article.type_choices
    section_obj = models.Section.objects.all()
    return render(request, 'search.html', {'article_obj': article_obj, 'types': types, 'section_obj': section_obj, 'kwargs': kwargs})

上面順便講了2種生成當前url的方法。這里最后是在后端獲取到了當前url的參數(shù),然后再返回給前端

在前端用模板語言實現(xiàn)

現(xiàn)在后端傳來的kwargs參數(shù),就是當前url動態(tài)的內(nèi)容的,所以當前的url是這樣的:

href="/search-{{ kwargs.section }}-{{ kwargs.type }}/"

獲取到上面的這個動態(tài)的url的式子,這小段的重點也就講完了。
剩下的就是熟練運用之前掌握的只是了,前端htlm的代碼如下:

<style>
    div.search-area>div {margin: 5px; font-size: large;}
    div.search-area a {display: inline-block; padding: 3px 5px; border: 1px solid gray;}
    div.search-area a:hover {display: inline-block; padding: 3px 5px; border: 1px solid red; text-decoration:none;}
    div.search-area a.active {background-color: blue; color: white;}
</style>
<div class="container">
    <div class="search-area">
        <h3>搜索條件</h3>
        <div>
            <span>版塊:</span>
            <a {% if kwargs.section == 0 %} class="active" {% endif %} href="/search-0-{{ kwargs.type }}/">全部</a>
            {% for section in section_obj %}
                <a {% if kwargs.section == section.id %} class="active" {% endif %} href="/search-{{ section.id }}-{{ kwargs.type }}/">{{ section.name }}</a>
            {% endfor %}
        </div>
        <div>
            <span>類型:</span>
            <a {% if kwargs.type == 0 %} class="active" {% endif %} href="/search-{{ kwargs.section }}-0/">全部</a>
            {% for type in types %}
                <a {% if kwargs.type == type.0 %} class="active" {% endif %} href="/search-{{ kwargs.section }}-{{ type.0 }}/">{{ type.1 }}</a>
            {% endfor %}
        </div>
    </div>
    <div>
        <h3>查詢結果</h3>
        <div class="list-group">
            {% for article in article_obj %}
            <a href="/article-{{ article.id }}/" class="list-group-item">
                {{ article.title }}
            </a>
            {% endfor %}
        </div>
    </div>
</div>

上面還對選中的項目加了一個樣式,同樣是判斷當前動態(tài)的url,如果url判斷后該項目是被選中的,則加上 class="active" 的樣式。

小結

  • 在 urls.py 里,路由的捕獲參數(shù)不能隨便寫,最好是和表的字段名一致(這樣之后都是直接引用,不用修改變量名了)
  • 后端處理函數(shù)里要寫一個for循環(huán),處理一下選擇全部傳入?yún)?shù)是0的問題。
  • 把kwargs這個url的參數(shù)也return給前端處理
  • href="/search-{{ kwargs.section }}-{{ kwargs.type }}/",在這個動態(tài)的url上修改

最后,上面的代碼比較長,看著也比較亂??梢杂媚0逭Z言的自定義函數(shù)封裝一下,這樣前端只需要寫一行就好了,而更加復雜的邏輯則放到 templatetags/*.py 自定義的模板函數(shù)里來實現(xiàn)。課上是這么做了,不過我

JSONP

JSONP是一種請求方式,解決瀏覽器的同源策略阻止跨域請求的問題。

準備

準備里了可以跳過,這里通過后端轉(zhuǎn)發(fā)請求,瀏覽器端不存在跨域的問題。但是這樣多了一個中間環(huán)節(jié)。
這里需要用到requests模塊,所以先安裝一下(或者不要裝了,直接看下面用瀏覽器直接發(fā)請求會報錯的情況):

pip install requests

然后去網(wǎng)上找一個api接口來請求,比如天氣api的接口:http://www.weather.com.cn/data/sk/101020100.html
如下寫一個處理函數(shù):

import requests
def get_res(request):
    response = requests.get('http://www.weather.com.cn/data/sk/101020100.html')  # 發(fā)起get請求
    # print(response.content)  # 返回的二進制內(nèi)容
    response.encoding = 'utf-8'  # 設置編碼格式,否則中文會是亂碼
    print(response.text)  # 返回的文本內(nèi)容
    return render(request, 'demo/jsonp.html', {'res': response.text})

然后記得配好urls.py的對應關系,開啟服務,頁面獲取一下內(nèi)容:

<div>
    {{ res }}
</div>

這樣,頁面請求后有返回的內(nèi)容的。但是上面的請求過程是前端往后端發(fā)請求,然后后端再去找api接口請求,把api接口返回的結果再返回給前端。但是前端也是可以直接給api接口發(fā)請求的,而不用經(jīng)過后端的中轉(zhuǎn)。

直接使用瀏覽器發(fā)請求

直接從瀏覽器發(fā)請求,就會出現(xiàn)跨域的問題了。下面先來觸發(fā)這個問題。
直接修改前端代碼:

<h3>后臺獲取的結果:</h3>
<p>{{ res }}</p>
<h3>js直接獲取結果</h3>
<input type="button" value="獲取結果" onclick="getContent();" />
<p id="container"></p>
<script>
    function getContent() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://www.weather.com.cn/data/sk/101020100.html');
        xhr.onreadystatechange = function () {
            console.log(xhr.responseText);  // 這里不能alert看結果
        };
        xhr.send();
    }
</script>

打開后臺,查看控制臺的信息,就是下面這句報錯信息:

SEC7120: [CORS] 原點“http://127.0.0.1:8000”未在“http://www.weather.com.cn/data/sk/101020100.html”的 cross-origin  資源的 Access-Control-Allow-Origin response header 中找到“http://127.0.0.1:8000”。

這里的情況是,數(shù)據(jù)已經(jīng)發(fā)出了,并且服務器也處理并返回了。報錯的信息是由于瀏覽器的同源策略,拒絕接收。

本地重現(xiàn)跨域的問題

上面是會有出現(xiàn)問題的場景,現(xiàn)在本地來重現(xiàn)一下跨域的場景。
處理函數(shù)很簡單:

def jsonp(request):
    return HttpResponse('OK')

全端頁面只需要把請求的url參數(shù)修改一下:

        xhr.open('GET', 'http://127.0.0.1:8000/demo/jsonp/');

如果用默認的 127.0.0.1:8000 這個本地域名訪問,是不跨域的。用這個地址 localhost:8000 來訪問,也是訪問本地,然后再向 http://127.0.0.1:8000 發(fā)請求,就被認為跨域了。
另外還有一個方法,去settiongs.py里修改設置一下下面這個參數(shù):

ALLOWED_HOSTS = []

這里提一下,就不展開了。

通過JSONP支持跨域

瀏覽器有同源策略,但是其實并不是所有的請求都會被同源策略阻止。比如:
cdn: &lt;script src="http://lib.sinaapp.com/js/jquery/1.12.4/jquery-1.12.4.min.js"&gt;&lt;/script&gt;
圖片: &lt;img src="/upload/otherpic48/122381.jpg"&gt;
可能是所有的有src屬性的標簽,都不受同源策略的影響。
這里就要通過script標簽來繞過瀏覽器的同源策略,把前端的按鈕事件綁定到下面這個新的函數(shù)上:

<script>
    function getJSONP() {
        var tag = document.createElement('script');
        tag.src = 'http://127.0.0.1:8000/demo/jsonp/';
        document.head.appendChild(tag)
    }
</script>

上面這個函數(shù)的效果是,創(chuàng)建一個script標簽,設置了src后,追加到head標簽里。瀏覽器處理的時候,就會添加這個script標簽,并且會去src的地址獲取內(nèi)容,并且由于這是一個script標簽,所以獲取到的內(nèi)容,瀏覽器更當做js語句來處理。這里由于獲取到的是 return HttpResponse('OK') ,js語法錯誤,所以還是會有個錯誤信息。修改一下處理函數(shù),返回一句js語句看看:

def jsonp(request):
    return HttpResponse("alert('OK');")

然后現(xiàn)在再看看效果,點擊按鈕后,會解析并執(zhí)行返回的 alert('OK'); 這句js語句。
現(xiàn)在修改一下處理函數(shù),返回一個復雜一點的JSON字符串,并且使用一個自定義個函數(shù)名,字符串作為函數(shù)的參數(shù):

import json
def jsonp(request):
    res = {'status': True, 'data': 'Test123'}
    return HttpResponse("callback(%s);" % json.dumps(res))

然后前端也要定義好這個自定義的js函數(shù):

<input type="button" value="獲取結果" onclick="getJSONP();" />
<script>
    function getJSONP() {
        var tag = document.createElement('script');
        tag.src = 'http://127.0.0.1:8000/demo/jsonp/';
        document.head.appendChild(tag)
    }
    function callback(arg) {
        alert(JSON.stringify(arg))
    }
</script>

現(xiàn)在的效果就是,前端通過script標簽,跨域接收到了一個callback函數(shù)調(diào)用的命令,并且參數(shù)就是我們需要的數(shù)據(jù)。自己通過在頁面里定義這個callback函數(shù),就可以獲取到返回的數(shù)據(jù)了。如此成功的繞開了瀏覽器的同源策略,實現(xiàn)了跨域請求。

繼續(xù)優(yōu)化JSONP

上面還有2個問題:

  • 回調(diào)函數(shù)的函數(shù)名寫死了,可能會和本地的函數(shù)名重名
  • 每請求一次,都會生成一個script標簽

先把處理函數(shù)修改一下解決第一個問題:

import json
def jsonp(request):
    func = request.GET.get('callback', 'callback')
    res = {'status': True, 'data': 'Test123'}
    return HttpResponse("%s(%s);" % (func, json.dumps(res)))

現(xiàn)在發(fā)送get請求的時候可以通過callback參數(shù)來指定需要函數(shù)的回調(diào)函數(shù)的函數(shù)名。之前的前端不用修改,依然可以使用。
一般約定這個指定返回的函數(shù)的函數(shù)名的key就是callback
然后修改前端,這次回調(diào)函數(shù)換一個名字試試。另外還要解決第二個問題,就是獲取回復數(shù)據(jù)之后,把之前生成的script標簽移除掉:

<input type="button" value="獲取結果" onclick="getJSONP();" />
<script>
    function getJSONP() {
        var tag = document.createElement('script');
        tag.src = 'http://127.0.0.1:8000/demo/jsonp/?callback=myJSONP';  // get請求加一個callback參數(shù)
        document.head.appendChild(tag);
        document.head.removeChild(tag);  // 移除創(chuàng)建的標簽
    }
    function myJSONP(arg) {
        alert(JSON.stringify(arg))
    }
</script>

JSONP只能發(fā)get請求。使用jQuery的話,就算指定method是POST,jQuery內(nèi)部也是轉(zhuǎn)成GET處理的。

jQuery發(fā)送JSONP

這里主要看一下jQuery的用法。基本上使用了jQuery之后,和發(fā)送普通的AJAX請求形式差不多:

<input type="button" value="獲取結果" onclick="jqJSONP();" />
<script src="http://lib.sinaapp.com/js/jquery/1.12.4/jquery-1.12.4.min.js"></script>
<script>
    function jqJSONP() {
        $.ajax({
            url: 'http://127.0.0.1:8000/demo/jsonp/',
            type: 'POST',  // 沒用,因為發(fā)的還是GET
            dataType: 'jsonp',  // 指定使用jsonp來發(fā)送這個請求
            jsonp: 'callback',  // 就是指定回調(diào)函數(shù)的參數(shù)的key
            jsonpCallback: 'myJSONP'  // 指定回調(diào)函數(shù)的函數(shù)名,和上面的和起來就是 ?callback=myJSONP
        })
    }
    function myJSONP(arg) {
        alert(JSON.stringify(arg))
    }
</script>

CORS(跨站資源共享)

解決跨域的問題,除了上面的JSONP,還有這個CORS。
講師的博客:https://www.cnblogs.com/wupeiqi/p/5703697.html
在最后有介紹,課上沒展開講。

XSS過濾

XSS×××是通過對網(wǎng)頁注入可執(zhí)行代碼且成功地被瀏覽器執(zhí)行,達到×××的目的。這里主要講針對富文本編輯器的情況。
在使用富文本編輯器的時候,尤其要注意XSS×××。因為別的地方還可以過濾html標簽,但是富文本編輯器本身就要使用html標簽,如果全部過濾掉,就無法正常顯示文檔格式了。
防范的手段就是把特定的標簽過濾掉,比如script標簽。最安全的做法就是設置白名單,留著編輯器使用的標簽,其他的全部過濾。編輯器可能會自帶過濾,不過前端XSS過濾都會被繞過,只有在后端過濾才能萬無一失。
通用的手段就是,在收到數(shù)據(jù)提交之后進行過濾,然后把過濾后的數(shù)據(jù)保存到數(shù)據(jù)庫。保存后的數(shù)據(jù)就認為是安全的,之后頁面顯示的時候,就一律放行。
過濾標簽的方法當然可以通過正則匹配來實現(xiàn)。不過這里推薦一個模塊,beatifulsoup4。安裝模塊:

pip install beautifulsoup4  

另外這個模塊貌似也是爬蟲利器,都是要處理html標簽嘛。

查找標簽-清空、清除

下面是BeautifulSoup的基本用法,使用find()方法找到指定的標簽,然后清除掉:

content = """
<h2>測試頁面</h2>
<p class="c1">
    第一個段落<span class="color" >這里是紅色的</span>
    <script>alert('p1');</script>
</p>
<p class="c2 p2" id="i2">
    第二個段落<strong id="click" onclick="alert('p2');">點我看看</strong>
</p>
<p class="c3" id="i3">
    第三個段落
    <script>alert('p3');</script>
</p>
"""

from bs4 import BeautifulSoup
# 下面第二個參數(shù)是指定解析器,這個是python標準庫內(nèi)置的。也支持其他第三方的解析器(需安裝)
soup = BeautifulSoup(content, "html.parser")
tag = soup.find('script')  # 查找第一個標簽
while tag:  # 這個循環(huán)應該是能把所有的標簽都查找出來了
    print(tag)
    # tag.hidden = True  # 去掉注釋,可以把整個空標簽也去掉,否則就是去掉標簽的內(nèi)容,保留標簽
    tag.clear()  # 清空標簽里的內(nèi)容
    tag = tag.find_next('script')  # 查找后一個標簽
content = soup.decode()  # 轉(zhuǎn)成字符串
print(type(content), content)

HTML解析器,這里用了python自帶的,就不用另外安裝了。也有其他第三方更好的,但是需要安裝,就看怎么取舍了。
如歌直接打印soup,print(soup),顯示的效果也是一樣的。但是soup本身是 &lt;class 'bs4.BeautifulSoup'&gt;,直接打印這個對象的時候,內(nèi)部調(diào)用的也是return self.encode()。

查找標簽的屬性-清除

還是上面的html,進一步處理以下標簽中的屬性

from bs4 import BeautifulSoup
# 下面第二個參數(shù)是指定解析器,這個是python標準庫內(nèi)置的。也支持其他第三方的解析器(需安裝)
soup = BeautifulSoup(content, "html.parser")
tag = soup.find('script')  # 查找第一個標簽
while tag:  # 這個循環(huán)應該是能把所有的標簽都查找出來了
    print(tag)
    tag.hidden = True
    tag.clear()  # 清空標簽里的內(nèi)容
    tag = tag.find_next('script')  # 查找后一個標簽
span = soup.find('span')
print(span.attrs)  # 打印這個標簽的所有的屬性
del span.attrs['style']  # 刪除特定的屬性
strong = soup.find('strong')
print(strong.attrs)
del strong.attrs  # 刪除所有屬性
content = soup.decode()  # 轉(zhuǎn)成字符串
print(content, type(content), type(soup))

標簽白名單

這次設置一個白名單,只保留白名單中的標簽的內(nèi)容:

from bs4 import BeautifulSoup
soup = BeautifulSoup(content, "html.parser")
tags = ['p', 'span', 'strong']  # 設置一個白名單,下面只保留白名單的里的標簽內(nèi)容
# 下面的這個循環(huán),遍歷一遍所有的標簽
for tag in soup.find_all():
    if tag.name not in tags:
        tag.hidden = True
        tag.clear()
content = soup.decode()  # 轉(zhuǎn)成字符串
print(content)

包含標簽屬性的白名單。上面的做法,只處理了標簽,沒有處理標簽中的屬性。這里需要一個更加復雜的白名單:

from bs4 import BeautifulSoup
soup = BeautifulSoup(content, "html.parser")
tags = {
    'p': ('class', 'id'),  # 只允許class 和 id 這2個屬性
    'span': ('class',),
    'strong': (),  # 值允許標簽,不能帶任何屬性
}
# 下面的這個循環(huán),遍歷一遍所有的標簽
for tag in soup.find_all():
    if tag.name not in tags:
        tag.hidden = True
        tag.clear()
    else:  # 處理白名單的屬性,再遍歷一遍標簽的屬性
        # 下面的list()相當于再復制了一份列表,然后遍歷這個列表。防止下面在迭代過程中禁止把迭代的元素刪除
        for attr in list(tag.attrs):
            if attr not in tags[tag.name]:
                del tag.attrs[attr]
content = soup.decode()  # 轉(zhuǎn)成字符串
print(content)

單例模式

一個類,每次實例化都會生成一個對象:

class Foo(object):

    def __init__(self):
        pass

c1 = Foo()
c2 = Foo()
print(c1, c2)

# 結果如下:
# <__main__.Foo object at 0x0000018AAF5C8A20> <__main__.Foo object at 0x0000018AAF76A2B0>

上面的情況,生成了2個對象,每個對象分別占用各自的內(nèi)存空間。
下面自定義了一個方法,用這個方法生成對象時候,只有對一次會創(chuàng)建實例,之后用的都是第一次的對象:

class Foo(object):
    __instance = None

    def __init__(self):
        pass

    @classmethod
    def get_instance(cls):
        if not Foo.__instance:
            Foo.__instance = Foo()
        return Foo.__instance

    def process(self):
        return 'Foo.process'

c1 = Foo.get_instance()
c2 = Foo.get_instance()
print(c1.process(), c2.process())
print(c1, c2)

# 結果如下:
# Foo.process Foo.process
# <bound method Foo.process of <__main__.Foo object at 0x0000022276B0A320>> <bound method Foo.process of <__main__.Foo object at 0x0000022276B0A320>>

為了更加直觀的說明問題,我這個類里還定義了一個process方法,返回的結果也是不變的。所以這種情況下,這個類不需要多個實例,因為每個實例返回的結果都是一樣的。也就是說,這種類,只需要一個實例,即只有在第一次實例化的時候需要創(chuàng)建對象,之后每次都只需要用之前創(chuàng)建的對象就好了,不用另外再創(chuàng)建對象了。
最LOW的做法大概就是,自己再實例化這個類后,把創(chuàng)建的對象保存下來,之后不要再進行實例化操作了。上面的例子中使用了特定的方法來進行實例化,之后再第一次實例化的時候才會創(chuàng)建對象。從打印的結果來看,c1 和 c2 的內(nèi)存地址是一樣的。
上面的例子算是實現(xiàn)效果,但是改變了調(diào)用的方法。并且依然是可以用標準的方法來創(chuàng)建不同的對象的。下面的例子通過定義new方法,實現(xiàn)了真正的單例模式:

class Foo(object):
    __instance = None

    def __init__(self):
        pass

    # 單例模式,就是處在類里加上這個new方法和上面的__instance靜態(tài)屬性
    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls, *args, **kwargs)
        return cls.__instance

    def process(self):
        return 'Foo.process'

c1 = Foo()
c2 = Foo()
print(c1.process(), c2.process())
print(c1, c2)

# 結果如下:
# Foo.process Foo.process
# <__main__.Foo object at 0x000001DF3132A2E8> <__main__.Foo object at 0x000001DF3132A2E8>

上面如果注釋掉new方法,process方法返回的結果是一樣的,但是每個對象占用的內(nèi)存就是不同的了(浪費資源)。如果一個類,它的每個對象里封裝的內(nèi)容都是一樣的,就可以使用單例模式。
所以實現(xiàn)了單例模式后,調(diào)用類中的方法可以實例化之后直接調(diào)用方法或?qū)傩裕?/p>

res = Foo().process()

Django的事務操作

Django提供了單獨API來控制事務:

atomic(using=None, savepoint=True)[source] 

原子性是數(shù)據(jù)庫事務的一個屬性。使用atomic,我們就可以創(chuàng)建一個具備原子性的代碼塊。一旦代碼塊正常運行完畢,所有的修改會被提交到數(shù)據(jù)庫。反之,如果有異常,更改會被回滾。
被atomic管理起來的代碼塊還可以內(nèi)嵌到方法中。這樣的話,即便內(nèi)部代碼塊正常運行,如果外部代碼塊拋出異常的話,它也沒有辦法把它的修改提交到數(shù)據(jù)庫中。
一般還是用下面例子中的方法來使用把。

作為裝飾器來使用的例子

from django.db import transaction

@transaction.atomic
def viewfunc(request):
    # This code executes inside a transaction.
    do_stuff()

作為上下文管理器來使用的例子:

from django.db import transaction

def viewfunc(request):
    # This code executes in autocommit mode (Django's default).
    do_stuff()

    with transaction.atomic():
        # This code executes inside a transaction.
        do_more_stuff()

新聞名稱:Python自動化開發(fā)學習25-Django
網(wǎng)址分享:http://sd-ha.com/article10/ggscgo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、搜索引擎優(yōu)化、做網(wǎng)站、用戶體驗、品牌網(wǎng)站建設、標簽優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應式網(wǎng)站建設