不忘初心,
牢记使命。

Django模型层—ORM中的事务和锁、Ajax异步请求和局部刷新、Ajax文件上传、日期时间类型的

2021-04-04 大聪明 0评论 156 0喜欢

Django模型层---ORM中的事务和锁

行级锁

entries = Entry.objects.select_for_update().filter(author=request.user)  #加互斥锁,由于mysql在查询时自动加的是共享锁,所以我们可以手动加上互斥锁。create、update、delete操作时,mysql自动加行级互斥锁

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): #其实不用这么负载,直接在orm创建表的时候,给这个表定义一个lock和unlock方法,借助django提供的connection模块来发送锁表的原生sql语句和解锁的原生sql语句就可以了,不用外层的这个LckingManager(model.Manager)类

        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

事务

开启事务后,做完操作,不commit,不会改变。

1. 全局的
    settings文件配置
2. 局部
    视图函数
    from django.db import transaction
    @transaction.atomic
    def index(request):
        pass orm...sql
        return xxx
    上下文逻辑里边
    def index(request):
        ...
        with transaction.atomic():
            pass
        ...
        return xxx

Ajax

参考:https://www.cnblogs.com/clschao/articles/10468335.html

特性:
    1.异步请求
    2.局部刷新
    <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)
            }
        })
    })

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': '用户名或者密码错误!!!'}
            ret = json.dumps(ret)
            # return HttpResponse(ret)
            return HttpResponse(ret, content_type='application/json') # 加上这个后在ajax中就不必在进行json解析了

class IndexView(View):
    def get(self,request):
        return render(request, 'index.html')
# login.html
<body>
<h1>你好,世界!</h1>
<form action="/login/" method="post">
    {% csrf_token %}
    用户名: <input type="text" id="username" name="username">
    密码:   <input type="password" id="password" name="password">
{#    submit和button就会触发form表单请求#}
{#    <input type="submit" id="btn">#}
{#    <button></button>#}
    <input type="button" id="btn" value="提交">
</form>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/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
# 这种回复最方便,直接Json了,也不用导入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') # 加上这个后在ajax中就不必在进行json解析了

form表单上传文件

{#enctype="multipart/form-data"  必须指定contenttype#}
<form action="/upload/" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    头像:<input type="file" name="headicon">
    用户名:<input type="text" name="name">
    密码:<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: 佩奇.png (image/png)>]}>
        file_obj = request.FILES.get('headicon') # 文件数据需要用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() # 一次返回65536B,可以设置chunck_size的大小
            f.write(chunck)
        return HttpResponse('ok')

ajax文件上传

Ajax头像:<input type="file" id="file">
Ajax用户名<input type="text" id="uname">
<button id="btn">提交</button>

<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="{% static 'js/jquery.js' %}"></script>

<script>
    $('#btn').click(function () {
        var formdata = new FormData();  // 可以携带文件数据
        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, // 不处理数据
            contentType:false, // 不设置内容类型
            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: 佩奇.png (image/png)>]}>
        # file_obj = request.FILES.get('headicon') # 文件数据需要用request.FILES去拿
        file_obj = request.FILES.get('file_obj')  # 文件数据需要用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():  # 一次饭hi65536B
                f.write(chunk)

        return HttpResponse('ok')

时间日期类型不可json问题

import json
from datetime import datetime
from datetime import date

#对含有日期格式数据的json数据进行转换
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)

多表作业

# 获取作者
# 方式1
<td>
    {% for author in book.authors.all %}
    {{ author.name }}
    {% if forloop.last %}

    {% else %}
        ,
    {% endif %}
    {% endfor %}
</td>
# 方式2
# 在Book类中增加方法
def get_author_name(self):
    # author_list = self.authors.all()
    # author_name_list = [author.name for author in author_list]
    # ret = ','.join(author_name_lis)
    # return ret
    return ','.join([author.name for author in self.authors.all())
# html文件中
<td>
    {{ book.get_author_name }}
</td>

发表评论 取消回复

电子邮件地址不会被公开。

请输入正确格式的qq邮箱
请输入以http或https开头的URL,格式如:https://libo_sober.top