ORMにおけるトランザクションとロック、Ajaxによる非同期リクエストと部分リフレッシュ、Ajaxによるファイルアップロード、日時指定Json、マルチテーブルクエリブックのシステム
I. ORM におけるトランザクションとロック
トランザクション
アトミック性を確保するためのトランザクション
"""
Transactions
ACID
Atomicity: the smallest unit that cannot be separated
Consistency: complementary to atomicity
Isolation: Transactions do not interfere with each other
Persistence: Once a transaction is confirmed, it is permanent
Rollback of a transaction
rollback
Confirmation of a transaction
commit
"""
# currently requires
from django.db import transaction
with transaction.atomic(): open transaction
# sql1
# sql2
# All orm operations written in the with block are part of the same transaction
print("perform other operations")
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
import django
django.setup()
from app01 import models
from django.db import transaction
from django.db.models import F, Q
# Transactions to ensure atomicity
# Atomicity: An atomic transaction is either executed in its entirety or simply not executed at all. This means that every task in a unit of work must be executed correctly. If any task fails to execute, the entire unit of work or transaction is terminated.
try:
with transaction.atomic(): # Open the transaction
# A series of operations
models.Book.objects.all().update(kucun=F("kucun") - 10)
models.Book.objects.all().update(sale=F("sale") + 10)
except Exception as e:
print(e)
ここでは、さらにトランザクションを設定するための小さな原則を紹介します。
1. トランザクションを短くする
2. トランザクションのロールバックを避けるようにする
3. セーブポイントを回避する
4. デフォルトでは、悲観的なロックに依存します。
5. 5. スループットを重視するトランザクションには楽観的ロックを考慮する
6. トランザクションを開くためのステートメントを表示する
7. ロックされる行数は少ないほどよく、またロックされる時間は短いほどよい
ロック
行レベルロック
entries = Entry.objects.select_for_update().filter(author=request.user) # Add a mutually exclusive lock, because mysql automatically adds a shared lock when querying, so we can manually add a mutually exclusive lock. create, update, delete operations, mysql automatically adds row-level mutex lock
SELECT * FROM t1 WHERE id=1 FOR UPDATE;
model.T1.objects.select_for_update().filter(id=1)
テーブルロック
class LockingManager(models.Manager):
""" Add lock/unlock functionality to manager.
Example::
Class Job(models.Model): # actually do not have to be so loaded, directly in orm when creating a table, to the table to define a lock and unlock methods, with the connection module provided by django to send a native sql statement to lock the table and unlock the native sql statement can be, without the outer layer of this LckingManager(model.Manager) class
manager = LockingManager()
counter = models.IntegerField(null=True, default=0)
@staticmethod
def do_atomic_update(job_id)
''' Updates job integer, keeping it below 5 '''
try:
# Ensure only one HTTP request can do this update at once.
Job.objects.lock()
job = Job.object.get(id=job_id)
# If we don't lock the tables two simultanous
# requests might both increase the counter
# going over 5
if job.counter < 5:
job.counter += 1
job.save()
finally:
Job.objects.unlock()
"""
def lock(self):
""" Lock table.
Locks the object model table so that atomic update is possible.
Simulatenous database access request pend until the lock is unlock()'ed.
Note: If you need to lock multiple tables, you need to do lock them
Note: If you need to lock multiple tables, you need to do lock them all in one SQL clause and this function is not enough.
dead lock, all tables must be locked in the same order.
See http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
"""
cursor = connection.cursor()
table = self.model._meta.db_table
logger.debug("Locking table %s" % table)
cursor.execute("LOCK TABLES %s WRITE" % table)
row = cursor.fetchone()
return row
def unlock(self):
""" Unlock the table. """
cursor = connection.cursor()
table = self.model._meta.db_table
cursor.execute("UNLOCK TABLES")
row = cursor.fetchone()
return row
II. Ajax
www.cnblogs.com/clschao/art を参照...
1. はじめに
AJAX(Asynchronous Javascript And XML)は、中国語に訳すと「非同期型JavaScriptとXML」です。つまり、Javascript言語を使ってサーバーと非同期でやり取りし、転送されるデータはXMLです(もちろん、転送されるデータはXMLだけでなく、現在はjsonデータも多く使用されています)。
AJAXは新しいプログラミング言語ではなく、既存の標準を利用した新しい方法です。
AJAXの最大の利点は、ページ全体を再読み込みすることなく、サーバーとデータのやり取りを行い、ページの一部を更新できることである。(この機能により、ユーザーにはリクエストとレスポンスの処理が知らず知らずのうちに行われているような印象を与えることができる)。
AJAXはブラウザのプラグインを必要としませんが、ユーザーがブラウザ上でJavaScriptを実行することを許可する必要があります。
a. 同期型インタラクション:クライアントがリクエストを送信した後、サーバーの応答が終了するのを待ってから2回目のリクエストを送信する必要があります。
b.非同期インタラクション。クライアントがリクエストを行った後、サーバーの応答が終了するのを待たずに2回目のリクエストを行う。
AJAXの特徴として、非同期の他に、ブラウザのページが部分的に更新されるというものがあります(この機能は、ユーザーにリクエストとレスポンスの処理が知らない間に行われているような印象を与えます)。
Features.
1. Asynchronous request
2. partial refresh
<script>
$('#btn').click(function () {
$.ajax({
{#url:'/login/',#}
url:"{% url 'login' %}",
type:'post',
data:{
csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val(),
{#csrfmiddlewaretoken:"{
{ csrf_token }}",#}
name:$('#username').val(),
pwd:$('#password').val(),
},
success:function (res) {
var resStr = JSON.parse(res)
if (resStr['code'] == 0){
location.href=resStr['redirect_url']
}else{
if(resStr['code'] == 3){
var spanEle = document.createElement('span');
$(spanEle).text(resStr['warning'])
$('form').append(spanEle)
}
}
console.log(resStr)
}
})
})
2. ajaxのリクエストとレスポンス
# urls.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'^login/', views.LoginView.as_view(),name='login'),
url(r'^index/', views.IndexView.as_view()),
]
# views.py
class LoginView(View):
def get(self, request):
# return render(request, reverse('login'))
return render(request, 'login.html')
def post(self, request):
# name = request.POST.get('username')
# password = request.POST.get('passwoame')
name = request.POST.get('name')
password = request.POST.get('pwd')
print(name, password)
if name == 'laowang' and password == '123':
ret = {'code': 0, 'redirect_url': '/index/'}
ret = json.dumps(ret)
return HttpResponse(ret)
else:
ret = {'code':3,'warning': 'username or password error!}
ret = json.dumps(ret)
# return HttpResponse(ret)
return HttpResponse(ret, content_type='application/json') # Add this to ajax and you don't have to do json parsing
class IndexView(View):
def get(self,request):
return render(request, 'index.html')
# login.html
<body>
<h1> Hello, world! </h1>
<form action="/login/" method="post">
{% csrf_token %}
Username: <input type="text" id="username" name="username">
password: <input type="password" id="password" name="password">
{# submit and button will then trigger the form request #}
{# <input type="submit" id="btn">#}
{# <button></button>#}
<input type="button" id="btn" value="submit">
</form>
<! -- jQuery (all of Bootstrap's JavaScript plugins rely on jQuery, so it must be in front of them) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script>
$('#btn').click(function () {
$.ajax({
{#url:'/login/',#}
url:"{% url 'login' %}",
type:'post',
data:{
csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val(),
{#csrfmiddlewaretoken:"{
{ csrf_token }}",#}
name:$('#username').val(),
pwd:$('#password').val(),
},
success:function (res) {
// var resStr = JSON.parse(res)
if (resStr['code'] == 0){
location.href=resStr['redirect_url']
}else{
if(resStr['code'] == 3){
var spanEle = document.createElement('span');
$(spanEle).text(resStr['warning'])
$('form').append(spanEle)
}
}
console.log(resStr)
}
})
})
</script>
</script>
</body>
from django.http import JsonResponse
# This kind of response is the most convenient, direct Json, and no need to import Json
if name == 'laowang' and password == '123':
ret = {'code': 0, 'redirect_url': '/index/'}
# ret = json.dumps(ret)
return JsonResponse(ret)
# return HttpResponse(ret, ontent_type='application/json') # Add this and you don't need to parse json in ajax
III. ファイルをアップロードするためのフォーム
{#enctype="multipart/form-data" must specify contenttype#}
<form action="/upload/" method="post" enctype="multipart/form-data">
{% csrf_token %}
avatar: <input type="file" name="headicon">
Username: <input type="text" name="name">
Password: <input type="password" name="pwd">
<input type="submit">
</form>
# views.py
class UploadView(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
print(request.FILES) # <MultiValueDict: {'headicon': [<InMemoryUploadedFile: pech.png (image/png)>]}>
file_obj = request.FILES.get('headicon') # The file data needs to be taken with request.FILES
print(file_obj)
file_name = file_obj.name
path = os.path.join(settings.BASE_DIR, 'static', 'img', file_name) # with open('static/img/'+file_name, 'wb') as f:
with open(path, 'wb') as f:
# for i in file_obj:
# f.write(i)
for chunck in file_obj.chuncks() # return 65536B at a time, you can set the size of chunck_size
f.write(chunck)
return HttpResponse('ok')
ファイルのアップロード II
views.py
from django.shortcuts
import render, HttpResponsefrom django.views
import View# using the CBV pattern class Upload(View):
def get(self, request):
return render(request, "Upload.html")
def post(self, request): # Get the file before you must change the form form inside the enctype="multipart/form-data"
print(request.FILES) # <MultiValueDict: {'file_name': [<InMemoryUploadedFile: 1.jpg (image/jpeg)>]}> # Get the file uploaded by the user
file_path = request.FILES.get("file_name")
print(file_path, type(file_path)) # get is the file name 1.jpg<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
print(file_path.name, type(file_path.name)) # 1.jpg <class 'str'>
with open(file_path.name, "wb")as f: # Because file_path gets a file object, so to .name a bit
for i in file_path:
f.write(i)
return HttpResponse("ok")
Upload.html
{# Be sure to change the enctype="multipart/form-data, and don't forget the csrf_token #}
<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %}
<input type="file" name="file_name" >
<button>upload</button></form>
urls.pyurlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^upload/', views.Upload.as_view()), # don't forget the brackets
]
file_path.name: アップロードされたファイルの名前
フォーム用紙の注意点
-
formタグのaction属性は、投稿先アドレス(デフォルトのカレントアドレスは書かれていない)、リクエストメソッド(デフォルトはget)を指定します。
-
inputタグにはname属性が必要で、タグによってはvalueも必要です
-
type="submit"のボタンまたはinputタグを持つ(submitはsubmitのみ)。
# ここで method="get" であれば、元のurlを変更します。メールアドレスを入力してください。
<ラベル メールアドレス <ラベル パスワード<ラベル 選択した項目を記憶するサインイン
novalidate:フォーマットバリデーションなし
ここで、method="get"とすると、元のurl http://127.0.0.1:8000/login/?user=abc&pwd=123 : セキュリティが厳しくなくなる。
POST リクエストを送信するために必要な現在のアクションです。
setings.pyの中間キーをコメントアウトします。
MIDDLEWARE = [ # middle key 'django.middleware.security,
'django.contrib.sessions.middleware,
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', commented out to submit POST requests
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware,
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
urls.pyのデータを操作する(ログインに成功した場合はページを返し、ログインに失敗した場合は元のページを返します)
def login(requests):
print(requests, type(requests)) # Here's requests, a class
print(requests.method, type(requests.method)) # Get its method, POST GET
print(requests.POST, type(requests.POST.get("user"))) # Turn off an intermediate key before the POST request
# Logic for handling POST requests
if requests.method == "POST": # Get the user and password submitted by the user
user = requests.POST.get("user")
pwd = requests.POST.get("pwd") # Set a fixed value first (will be imported into the database later)
if user == "abc" and pwd == "123": # check success, return
return render(requests, "login2.html") # failed to verify
return render(requests, "login.html")
IV. ajax
ajaxファイルアップロード
Ajax avatar: <input type="file" id="file">
Ajax username<input type="text" id="uname">
<button id="btn">submit</button>
<! -- jQuery (all of Bootstrap's JavaScript plugins rely on jQuery, so it must be in front) -->
<script src="{% static 'js/jquery.js' %}"></script>
<script>
$('#btn').click(function () {
var formdata = new FormData(); // can carry file data
formdata.append('name', $('#uname').val());
formdata.append('file_obj', $('#file')[0].files[0]);
formdata.append('csrfmiddlewaretoken',
$('[name=csrfmiddlewaretoken]').val());
$.ajax({
url:'/upload',
type:'post',
{#data:{#}
{# name:$('#uname').val(),#}
{# file_obj:$('#file')[0].files[0],#}
data:formdata,
processData:false, // do not process data
contentType:false, // don't set the content type
success:function (res){
console.log(res)
}
})
})
</script>
class UploadView(View):
def get(self, request):
return render(request, 'upload.html')
def post(self, request):
print(request.FILES)
# <MultiValueDict: {'headicon': [<InMemoryUploadedFile: pech.png (image/png)>]}>
# file_obj = request.FILES.get('headicon') # file data needs to be taken with request.FILES
file_obj = request.FILES.get('file_obj') # The file data needs to be taken with request.
print(file_obj)
file_name = file_obj.name
path = os.path.join(settings.BASE_DIR, 'static', 'img', file_name)
# with open('static/img/'+file_name, 'wb') as f:
with open(path, 'wb') as f:
# for i in file_obj:
# f.write(i)
for chunk in file_obj.chunks(): # once rice hi65536B
f.write(chunk)
return HttpResponse('ok')
ajaxによる追加操作の完了
-
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^calc/', views.calc),
] -
views.py
def index(request):
return render(request, "index.html", locals())
def calc(request):
x1 = request.GET.get("x1")
x2 = request.GET.get("x2")です。
print(x1)
print(x2)
time.sleep(3) # 非同期テストのために3秒間休止する。
l3 = int(x1) + int(x2)
return HttpResponse(l3) # 計算結果はレスポンス内で返されます。 -
index.html
+ = 計算する
パラメータを受け取るためのajax操作
views.py
import json
from django.http.response
import JsonResponse
def text(request):
print(request.GET)
xqu = json.loads(request.GET.get("xqu")) # receive ajax parameters, pass the received string as json
print(xqu, type(xqu))
return JsonResponse({"status":200,"msg":"ok"}) # return information to ajax
html
$("#b3").click(function () {
$.ajax({
url:"/text/",
type:"get",
data:{ #ajax pass information to function
name: 'aaa',
age: 15,
xqu: JSON.stringify(['smoke','drink','perm']), # can pass string directly },
success:function (data) {
# Receive the information returned by the function
console.log(data)
console.log(data.msg)
console.log(data.status)
},
});
});
ajaxで削除する
アドレスジャンプで削除(ジャンプはページを更新することです)
htmlコード
{#implement ajax for delete function#}
<button url="{% url 'del' 'publisher' i.pk %}" class="btn btn-danger btn-sm" >delete</button>
$(".btn-danger").click(function () {
$.ajax({
url:$(this).attr('url'),
type:"get",
success:function (data) { // receive can't redirect, so receive the address // jump with address
location.href = data
}
})
})
views.py
@is_cookies
def delete(request, name, pk): # code
return HttpResponse(reverse(name)) # String returned
ジャンプせずに削除
htmlコード
{#implement ajax for delete function#}
<button url="{% url 'del' 'publisher' i.pk %}" class="btn btn-danger btn-sm" >delete</button>
ajax
<script>
$(".btn-danger").click(function () {
$.ajax({
url:$(this).attr('url'),
type:"get",
success:function (data) { //Receive can't redirect, so it receives the address //Jump with address
{#location.href = data#}
if(data.status===200){
//backend delete successful, front delete the line
_this.parent().parent().remove()
}
}
})
})
views.py
@is_cookies
def delete(request, name, pk): # code
return JsonResponse({"status":200}) # return a dictionary for ajax to extract if it's 200, then delete the th tag on this page
sweetalertの使用(ポップアップ効果)
Ajax削除時のSweetalertポップアップ効果、追加。
-
インポートスクリプト
複数のポップアップスタイルを持つ他のウェブサイト:sweetalert.js.org/guides/
AJAX素材サイト:www.cnblogs.com/maple-shaw/...
V. JSON
軽量テキストデータ交換フォーマット
パイソン
対応するデータ型
String Data Boolean List Dictionary None
シリアライズ
Data types for python --> json string
デシリアライズされた単語
json string --> python's data type
ビュー関数へのcsrfチェックサムの追加
方法1
from django.views.decorators.csrf
import csrf_exempt,csrf_protect@csrf_exempt Add to view This view does not require csrf checksum @csrf_protect Add to view This view requires csrf checksum @ensure_csrf_cookie Add to view Ensure that the return sets csrftoken's cookie
csrfチェックサムの原則
Get the csrftoken value from the cookie Get the csrfmiddlewaretoken value from request.POST or get the x-csrftoken value from the request header Compare the two values, accept the request if the comparison is successful, and reject it if not
ajax が django の csrf チェックサムを通過するようにします。
htmlのajaxにcsrfのチェックサムを追加する。
方法2
-
ajaxでcsrfmiddlewaretokenのキーと値のペアを直接データに追加します。
data:{ <未定義
csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken]').val()を使用します。
name: 'aaa',
年齢 15,
xqu: JSON.stringify(['smoking','drinking','perm']),
},
前提条件:csrftokenのクッキーが必要です。
-
csrf_token%}を使用します。
-
ビューに追加された ensure_csrf_cookie デコレータを使用します。
from django.views.decorators.csrf import ensure_csrf_cookie- x-csrftokenのキーと値のペアをヘッダーに追加する(ファイルをインポートすることで)。
1. ヘッダーをajaxに追加する
$.ajax({ <未定義
url:"/calc2/"。
タイプ: "post",
ヘッダを表示します。{"X-CSRFToken": KaTeX のパースエラーです。Expected 'EOF', got '}' at position 38: ...etoken]').val()}̲, // fetch c... ('[name="l11"]').val(),
"x2"。 KaTeX のパースエラーです。予想される 'EOF' は 43 番目の位置に '}' があります: ... }̲, ... /.test(method));}.
最終的な推奨:インポートファイル+クッキーがあることを確認する(この最後の1つ)
import json
from datetime import datetime
from datetime import date#Converts json data with date format data
class JsonCustomEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field,datetime):
return field.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(field,date):
return field.strftime('%Y-%m-%d')
else:
return json.JSONEncoder.default(self,field)d1 = datetime.now()
dd = json.dumps(d1,cls=JsonCustomEncoder)
print(dd)
関連
-
python error TypeError: 'bool' object is not subscriptable
-
DataFrameのソート問題
-
Pythonインストールモジュールエラー AttributeError: モジュール 'pip' には 'main' という属性がありません。
-
Python|ModuleNotFoundErrorを解決する。utils' という名前のモジュールがありません。
-
pipenvとpyenvによる複数の独立したPython仮想開発環境の管理
-
[Pythonノート】spyderのClearコマンド
-
アルゴリズム図 1.2 二項対立型ルックアップ TypeError: リストのインデックスは整数またはスライスでなければならず、float ではありません 解答
-
Python3 はエンコーディングの問題を解決します: UnicodeEncodeError: 'gbk' codec can't encode character '\xa9' in position
-
ValueError: 解凍するために1つ以上の値が必要です。
-
パイソン-ユニコード
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
'DataFrame' オブジェクトに 'sort' 属性がありません。
-
RuntimeWarning: ログでゼロによる除算に遭遇した
-
Solve ImportError: cannot import name 'np_utils' from 'tensorflow.keras.utils'
-
PythonのエラーNo module named 'pkg_resources' を解決する。
-
Python max()関数
-
ModuleNotFoundError: numpy.testing.decorators'という名前のモジュールがありません。
-
ModuleNotFoundError: Pythonソリューションに'scipy'という名前のモジュールがありません。
-
Pythonの学習における問題点
-
Mac環境でのbrewコマンドが見つからないエラーの解決方法
-
AttributeError: 'dict' オブジェクトには 'iteritems' という属性がありません。