Transactions and locks in ORM

This is the fourth day of my participation in Gwen Challenge

The transaction

Transactions are guaranteed atomicity

Consistency: atomicity is complementary to atomicity Isolation: transactions do not interfere with each other Persistence: once a transaction is confirmed to be permanent rollback of a transaction Rollback Confirmation of a transaction commit
# For now
from django.db import transaction

withTransaction.atomic (): Starts a transaction# sql1
    # sql2
    All ORM operations written in the with block of # are part of the same transaction
print("Perform other operations")
Copy the code
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 must be atomic
# atomicity: An atomic transaction either executes completely or not at all. This means that every task in the unit of work must be executed correctly. If any task fails, the entire unit of work or transaction is terminated.
try:
    with transaction.atomic(): # start 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)
Copy the code

Here are some guidelines for setting up transactions:

1. Keep things short

2. Avoid rollback in a transaction

3. Avoid savepoint

4. Pessimistic locking is relied on by default

5. Consider optimistic locking for throughput demanding transactions

6. Display declaration to open transaction

7. Lock as few rows as possible and for as short a time as possible

The lock

Row-level locks

entries = Entry.objects.select_for_update().filter(author=request.user)  Mysql mysql automatically adds a shared lock to a query, so we can manually add a mutex. Mysql automatically adds a row-level mutex to create, update, and delete operations

SELECT * FROM t1 WHERE id=1 FOR UPDATE;
model.T1.objects.select_for_update().filter(id=1)
Copy the code

Table locks

class LockingManager(models.Manager) :
    """ Add lock/unlock functionality to manager. Example:: class Job(models.Model): Lock and unlock methods are used to create a table, and djangoconnection module is used to send native SQL statements and unlock statements to the table. 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 all in one SQL clause and this function is not enough. To avoid 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
Copy the code

Second, the Ajax

Refer to www.cnblogs.com/clschao/art…

 1. Introduction

Asynchronous Javascript And XML (AJAX) translates to “Asynchronous Javascript And XML” in Chinese. This is the asynchronous interaction with the server using the Javascript language, transferring data as XML (not just XML, of course, but json data now).

AJAX is not a new programming language, but a new way to use existing standards.

The biggest advantage of AJAX is that you can exchange data with the server and update parts of the web without reloading the entire page. (This feature gives the user the impression that the request and response process is completed unknowingly)

AJAX does not require any browser plug-ins, but requires the user to allow JavaScript to execute on the browser.

A. Synchronous interaction: The client sends a request and waits for the server to complete the response before sending a second request.

B. Asynchronous interaction: After the client sends a request, it can send a second request without waiting for the end of the server response.

AJAX in addition to asynchronous features, there is also a browser page local refresh; (This feature gives the user the impression that the request and response process is being completed unknowingly

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) } }) })Copy the code

Ajax requests and responses

# 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': 'Wrong username or password!! '} ret = json.dumps(ret) # return HttpResponse(ret) return HttpResponse(ret, Content_type ='application/json') # def get(self,request): return render(request, 'index.html') # login.html<body>
<h1>Hello world!</h1>
<form action="/login/" method="post">{% csrf_token %} User name:<input type="text" id="username" name="username">Password:<input type="password" id="password" name="password">{# submit and button trigger the form request #} {#<input type="submit" id="btn"># #} {<button></button>#}
    <input type="button" id="btn" value="Submit">
</form>
<! -- jQuery (all JavaScript plug-ins for Bootstrap rely on jQuery and must be placed first) -->
<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>
Copy the code
from django.http import JsonResponse
# This kind of reply is the most convenient, directly Json, also need not 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') # return HttpResponse(ret, ontent_type='application/json'
Copy the code

Upload the file in the form

{#enctype="multipart/form-data" must specify contenttype#}<form action="/upload/" method="post" enctype="multipart/form-data">{% csrf_token %}<input type="file" name="headicon">User name:<input type="text" name="name">Password:<input type="password" name="pwd">
    <input type="submit">
</form>
Copy the code
# views.py
class UploadView(View) :    
    def get(self, request) :        
        return render(request, 'upload.html')    
    def post(self, request) :        
        print(request.FILES)  # 
      
       ]}>
      
        file_obj = request.FILES.get('headicon') File data needs to be retrieved 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 once, you can set the size of chunck_size
            f.write(chunck)        
            return HttpResponse('ok')
Copy the code

File upload ii

views.py
from django.shortcuts 
import render, HttpResponsefrom django.views 
import ViewClass Upload(View):
def get(self, request) :        
    return render(request, "Upload.html")    
def post(self, request) :        Enctype ="multipart/form-data"
    print(request.FILES)  # 
      
       ]}> #
      
    file_path = request.FILES.get("file_name")        
    print(file_path, type(file_path))  # was obtained is the name of the file 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, we need to name it
        for i in file_path:                
            f.write(i)        
        return HttpResponse("ok")
Copy the code
Upload.html {# be sure to modify encType ="multipart/form-data, and don't forget csrf_token #}<form action="" method="post" enctype="multipart/form-data">    {% csrf_token %}    
<input type="file" name="file_name" >    
<button>upload</button></form>
Copy the code
urls.pyurlpatterns = [    
url(r'^admin/', admin.site.urls),    
url(r'^upload/', views.Upload.as_view()),  # Don't forget the parentheses
]
Copy the code

File_path. name: indicates the name of the file to be uploaded

Note:

  1. The action attribute of the form tag specifies the address to submit (not the default current address), and the method request method (default: GET).
  2. The input tag must have a name attribute, and some tags must also have a value
  3. There is either a button button or an input tag with type=”submit” (submit only)
<form class="form-signin" action="" method="post" novalidate>If method="get", it will change the original URL<h2 class="form-signin-heading">Please enter your E-mail address</h2>        
<label for="inputEmail" class="sr-only">Email address</label>        
<input type="email" name="user" id="inputEmail" class="form-control" placeholder="Email address" required="" autofocus="">        
<label for="inputPassword" class="sr-only">Password</label>        
<input type="password" name="pwd" id="inputPassword" class="form-control" placeholder="Password" required="">        
<div class="checkbox">            
    <label>                
        <input type="checkbox" value="remember-me">Remember my choice</label>        
</div>        
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>    
</form>
Copy the code

Novalidate: format verification is not performed

If here is method = “get”, will change the original url http://127.0.0.1:8000/login/? User =abc&pwd=123: security is not strict

The actions necessary to submit a POST request now:

Comment out an intermediate key in setings.py

MIDDLEWARE = [# middle key 'django. MIDDLEWARE. Security. SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', Commented out can submit POST request 'django. Contrib. Auth. Middleware. AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]Copy the code

Manipulate data in urls.py (return to page on successful login, return to original page on failed login)

def login(requests) :    
    print(requests, type(requests))  # requests here is a class
    print(requests.method, type(requests.method))  # GET it, POST GET
    print(requests.POST, type(requests.POST.get("user")))  # Turn off a middle key before POST requests
    # Logic to handle 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 (import database later)
        if user == "abc" and pwd == "123":            Check success, return
            return render(requests, "login2.html")    # check failed
   return render(requests, "login.html")
Copy the code

Four, ajax

Ajax file upload

Ajax image:<input type="file" id="file">Ajax user name<input type="text" id="uname">
<button id="btn">submit</button>
<! -- jQuery (all JavaScript plug-ins for Bootstrap rely on jQuery and must be placed first) -->
<script src="{% static 'js/jquery.js' %}"></script>
<script>$('#btn').click(function () { var formdata = new FormData(); / / can carry the 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, Function (res){console.log(res)}})}) function (res){console.log(res)}})}</script>
Copy the code
class UploadView(View) :    
    def get(self, request) :        
        return render(request, 'upload.html')    
    def post(self, request) :        
        print(request.FILES) 
        # 
      
       ]}>
      
        # file_obj = request.files. get('headicon') # file_obj = request.files. get('headicon') # file_obj = request.files. FILES
        file_obj = request.FILES.get('file_obj')  File data needs to be retrieved 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 chunk in file_obj.chunks():  # One meal hi65536B
                f.write(chunk)        
        return HttpResponse('ok')
Copy the code

Add with Ajax

  1. urls.py
urlpatterns = [    
    url(r'^admin/', admin.site.urls),    
    url(r'^index/', views.index),    
    url(r'^calc/', views.calc),
]
Copy the code
  1. 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)  Pause for 3 seconds to test asynchrony
    l3 = int(x1) + int(x2)    
    return HttpResponse(l3)  # in response gives me the result of the calculation
Copy the code
  1. index.html
<body>    
<input type="text" name="l1" >+    <input type="text" name="l2" >=    <input type="text" name="l3" >    
<button id="b1">To calculate</button>    
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>$("#b1").click(function () {$.ajax({url:"/calc/", type:"get", {#async:false); So there's no need data: #} {" x1 ": $(' [name =" l1 "]). The val (), "x2" : $(' [name = "l2"]). The val (),}, Success: the function (data) {{# to get to the x1, x2 value passed to the l3 #} $(' [name = "l3]]" '). The val (data)},}); });</script>
</body>
Copy the code

Ajax operations to receive parameters

views.py

import json
from django.http.response 
import JsonResponse
def text(request) :    
    print(request.GET)    
    xqu = json.loads(request.GET.get("xqu")) # Accept ajax parameters and pass the received string to JSON
    print(xqu, type(xqu))    
    return JsonResponse({"status":200."msg":"ok"})  # Return information to Ajax
Copy the code

html

$(" # b3). Click (function () {$. Ajax ({url: "/ text/" type:" get ", data: {# ajax to pass information function name: 'aaa' age: 15, xqu: Json.stringify ([' smoke ',' drink ',' hot ']), # can directly pass string}, Function (data) {console.log(data) console.log(data.msg) console.log(data.status)},}); });Copy the code

Delete with Ajax

Delete with address jump (jump is to refresh the page)

The HTML code

{# implement ajax implement 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 '), the type: "get", success: function (data) {/ / receiving can't redirect, Location. Href = data}})Copy the code

views.py

@is_cookies
def delete(request, name, pk) : 	# code
    return  HttpResponse(reverse(name))  # return string
Copy the code

Delete without jump

The HTML code

{# implement ajax implement 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 '), the type: "get", success: function (data) {/ / receiving can't redirect, {#location.href = data#} if(data.status===200){ _this.parent().parent().remove()}}})})Copy the code

views.py

@is_cookies
def delete(request, name, pk) : 	# code
    return JsonResponse({"status":200})  # return a dictionary and let Ajax extract the th tag from the page if it is 200
Copy the code

Use of Sweetalert (popover effect)

Remove and add sweetalert popover effect for Ajax

  1. Import the script
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
Copy the code
  1. Writing js files
<script>    
$(".btn-danger").click(function () {        
    swal({            
        title: "Actually delete data?".text: "Data cannot be recovered after deletion!".icon: "warning".buttons: true.dangerMode: true,        
})            
.then((willDelete) = > {                
    if (willDelete) {                    
    var _this = $(this)                   
    $.ajax({                        
        url: $(this).attr('url'),                        
        type: "get".success: function (data) { // The receiver can not be redirected, so the receiver is an address
            {#location.href  = data#}                            
            if (data.status === 200) {                                
            // Delete the backend successfully
            _this.parent().parent().remove()                                
            swal("Data deleted successfully!", {                                    
                icon: "success"}); }else {                                
                swal("Data deleted successfully!", {                                   
                icon: "error"}); }}})}else {                    
            swal("Data deletion failed!"); }}); }) </script>Copy the code

More variety of pop-ups style website: sweetalert.js.org/guides/

AJAX information network: www.cnblogs.com/maple-shaw/…

Five, the JSON

Lightweight text data interchange format

python

Supported data types

String data Boolean list dictionary None

serialization

Python data type –> JSON string

The sequence of words

Json string –> Python data type

Add CSRF validation to view functions

Method one:

from  django.views.decorators.csrf 
importCsrf_exempt,csrf_protect@csrf_exempt on view This view does not require CSRF check. @CSRF_Protect on view This view requires CSRF check. @enSURE_CSRF_cookie on view Make sure the cookie of the CSRFToken is set when you returnCopy the code

CSRF verification principle

Obtain the cSRFToken value from cookie obtain the CSRFmiddlewareToken value from request.POST or obtain the X-CsrFToken value from the request header compare the two valuesCopy the code

To make Ajax pass Django’s CSRF check:

Add CSRF validation to HTML ajax

Method 2:

  1. Add a cSRFMIDDLEWareToken key-value pair directly to the data in ajax
data:{ csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken]').val(), name: 'aaa', age: 15, xqu: Json.stringify ([' smoke ',' drink ',' hot ']),},Copy the code

Prerequisite: there must be a cSRFtoken cookie

  • Use {} % csrf_token %

  • Decorator, using enSURE_cSRF_cookie, on the view

    ​ from django.views.decorators.csrf import ensure_csrf_cookie

    1. Add x-csrFToken key-value pair to header (import file)
1.Add header to ajax $. Ajax ({url:"/calc2/".type:"post",            
    headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken]').val()}, // fetch the csrftoken from the Cookie and set it to the request header {#} #async:false
    data:{                
        "x1": $('[name="l11"]').val(),                
        "x2": $('[name="l22"]').val(),            
    },            
2. Static files_dirs [os.path.join(BASE_DIR,'static'Function getCookie(name) {var cookieValue = null;if(document.cookie && document.cookie ! = =' ') {        
        var cookies = document.cookie.split('; ');        
        for (var i = 0; i < cookies.length; i++) {            
            var cookie = jQuery.trim(cookies[i]);            // Does this cookie string begin with the name we want?            
            if (cookie.substring(0, name.length + 1) === (name + '=')) {                
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));       
                break; }}}return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {  
// these HTTP methods do not require CSRF protection  
return(/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }Copy the code

Final recommendation: Import file + make sure there are cookies (the last kind)

Data: www.cnblogs.com/maple-shaw/…

Time date type not JSON problem

import json
from datetime import datetime
from datetime import dateConvert json data that contains date-formatted 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)
Copy the code