Python全栈之路-Django(十)

1 ORM补充

from app01 import models


def test(request):
    # select_related 自动关联UserType表(inner join),可以关联多个
    q = models.UserInfo.objects.all().select_related('ut',)
    for row in q:
        print(row.name, row.ut.title)
    # prefetch_related 通过多次单表查询解决连表查询效率低的问题
    # select * from userinfo;
    # Django内部:select * from usertype where id in [1,2,3]
    # Django将两个结果集整合在一起
    q = models.UserInfo.objects.all().prefetch_related('ut', )
    for row in q:
        print(row.name, row.ut.title)

    return HttpResponse('...')

1.2 多对多操作

app01.models.py

class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField('Girl')  # 多对多


class Girl(models.Model):
    nick = models.CharField(max_length=32)


# class Love(models.Model):
#     b = models.ForeignKey('Boy')
#     g = models.ForeignKey('Girl')
#     class Meta:
#         unique_together = [    # 联合唯一索引
#             ('b', 'g')
#         ]

app01.views.py

# 数据库操作
from app01 import models


def test(request):
    # # select_related 自动关联UserType表(inner join),可以关联多个
    # q = models.UserInfo.objects.all().select_related('ut',)
    # for row in q:
    #     print(row.name, row.ut.title)
    # # prefetch_related 通过多次单表查询解决连表查询效率低的问题
    # # select * from userinfo;
    # # Django内部:select * from usertype where id in [1,2,3]
    # # Django将两个结果集整合在一起
    # q = models.UserInfo.objects.all().prefetch_related('ut', )
    # for row in q:
    #     print(row.name, row.ut.title)

    # 多对多
    # objs1 = [
    #     models.Boy(name='温艳杰'),
    #     models.Boy(name='杨振威'),
    #     models.Boy(name='苏浩智'),
    #     models.Boy(name='邹润成'),
    # ]
    # models.Boy.objects.bulk_create(objs1, 10)
    # objs2 = [
    #     models.Girl(nick='李智'),
    #     models.Girl(nick='韩星宇'),
    #     models.Girl(nick='秦镇'),
    #     models.Girl(nick='杨涵'),
    # ]
    # models.Girl.objects.bulk_create(objs2, 10)

    # models.Love.objects.create(b_id=1, g_id=1)
    # models.Love.objects.create(b_id=1, g_id=2)
    # models.Love.objects.create(b_id=2, g_id=4)
    # models.Love.objects.create(b_id=2, g_id=3)
    # models.Love.objects.create(b_id=3, g_id=3)
    # models.Love.objects.create(b_id=4, g_id=4)
    # models.Love.objects.create(b_id=4, g_id=2)

    # 1 和温艳杰有关联的姑娘的列表
    # 方法1:先找到该对象,然后通过反向操作获取girl相关信息
    # obj = models.Boy.objects.filter(name='温艳杰').first()
    # love_list = obj.love_set.all()
    # for row in love_list:
    #     print(row.g.nick)
    # 方法2: 遍历时跨表
    # love_list = models.Love.objects.filter(b__name='温艳杰')
    # for row in love_list:
    #     print(row.g.nick)
    # 方法3:values values_list
    # love_list = models.Love.objects.filter(b__name='温艳杰').values('g__nick')
    # for item in love_list:
    #     print(item['g__nick'])
    # love_list = models.Love.objects.filter(b__name='温艳杰').values_list('g__nick')
    # for item in love_list:
    #     print(item[0])
    # 方法4:select_related
    # love_list = models.Love.objects.filter(b__name='温艳杰').select_related('g')
    # for obj in love_list:
    #     print(obj.g.nick)

    # 2 查看和韩星宇有关系的男生
    # 方法1:
    # obj = models.Girl.objects.filter(nick='韩星宇').first()
    # love_list = obj.love_set.all()
    # for row in love_list:
    #     print(row.b.name)
    # 方法2:
    # love_list = models.Love.objects.filter(g__nick='韩星宇')
    # for row in love_list:
    #     print(row.b.name)
    # 方法3:
    # love_list = models.Love.objects.filter(g__nick='韩星宇').values('b__name')
    # for item in love_list:
    #     print(item['b__name'])
    # love_list = models.Love.objects.filter(g__nick='韩星宇').values_list('b__name')
    # for item in love_list:
    #     print(item[0])
    # 方法4:
    # love_list = models.Love.objects.filter(g__nick='韩星宇').select_related('b')
    # for obj in love_list:
    #     print(obj.b.name)
    #

    # ManyToManyField 会生成app01_boy_m表,即boy和girl关系表
    # 正向操作
    obj = models.Boy.objects.filter(name='温艳杰').first()
    print(obj.id, obj.name)
    # 往app01_boy_m添加与obj对象有关系的列
    # obj.m.add(3)     # 单值
    # obj.m.add(2, 4)  # 多值
    # obj.m.add(*[1,])   # 列表
    # 在关系表中删除与obj对象有关系的列
    # obj.m.remove(1)
    # obj.m.remove(2, 4)
    # obj.m.remove(*[3])
    # 重置
    # obj.m.set([3, 1, ])
    # 获取与obj有关系的女孩列表
    girl_list = obj.m.all().filter(nick='李智')  # q是girl对象
    for item in girl_list:
        print(item.nick)
    # 在关系表中删除所有与obj有关系的列
    # obj.m.clear()

    # 反向操作:
    obj = models.Girl.objects.filter(nick='韩星宇').first()
    print(obj.id, obj.nick)
    v = obj.boy_set.all()  # boy对象
    print(v)

    return HttpResponse('...')

2 CSRF

给用户生成一段随机字符串,用户提交数据时需要携带,否则返回403状态码,用于防范XSS攻击

<form action="/csrf1.html" method="post">
    {% csrf_token %}
    <input type="text">
    <input type="submit" value="提交">
</form>

不仅会写到form表单里,cookie里也会写入

全站禁用

# 'django.middleware.csrf.CsrfViewMiddleware',

局部禁用

from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_exempt  # 局部禁用
def csrf1(request):
    if request.method == 'GET':
        return render(request, 'csrf1.html')
    else:
        return HttpResponse('...')

局部应用:

from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_protect  # 局部使用
def csrf1(request):
    if request.method == 'GET':
        return render(request, 'csrf1.html')
    else:
        return HttpResponse('...')

2.1 ajax提交数据时携带CSRF

方法1:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/csrf1.html" method="post">
    {% csrf_token %}
    <input type="text" id="user">
    <input type="submit" value="提交">
    <input type="button" value="Ajax提交" onclick="submitForm();">
</form>
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    function submitForm() {
        var csrf = $('input[name=csrfmiddlewaretoken]').val();
        var user = $('#user').val();
        $.ajax({
            url:'csrf1.html',
            type: 'POST',
            data: {'user': user, 'csrfmiddlewaretoken': csrf},
            success:function (arg) {
                console.log(arg)
            }
        })
    }
</script>
</body>
</html>

方法2:

function submitForm() {
        var token = $.cookie('csrftoken')
        var user = $('#user').val();
        $.ajax({
            url:'csrf1.html',
            type: 'POST',
            headers:{'X-CSRFToken': token},
            data: {'user': user},
            success:function (arg) {
                console.log(arg)
            }
        })
    }

3 CBV补充

CBV应用装饰器(注:对于CSRF目前只能在类上加装饰器)

# 1.类上加装饰器
@method_decorator(csrf_exempt,name='dispatch')
class Foo1(View):
    def get(self,request):
        pass
    def post(self,request):
        pass
# 2.指定方法上加
class Foo2(View):
    @method_decorator(wrapper)
    def get(self,request):
        pass
    def post(self,request):
        pass

原文地址:https://www.cnblogs.com/wanyuetian/p/7122332.html