zoukankan      html  css  js  c++  java
  • Django进阶2

    一、ORM操作进阶

    ForeignKey关联

    示例models

    from django.db import models
    # Create your models here.
    class User(models.Model):
        name = models.CharField(max_length=32)
    
    class Host(models.Model):
        host_name = models.CharField(max_length=32)
        blong_to = models.ForeignKey("User")

    ForeignKey创建数据

    models.Host.objects.create(host_name="127.0.0.1",blong_to=models.User.objects.get(id=1))

    1、搜索条件使用 __ 连接  2、获取值时使用 . 连接

    user_list=models.Host.objects.filter(blong_to__name="lisi")    #一对多过滤条件
    
    for item in user_list:
        print(item.host_name,item.blong_to.name)  #取数据,在前端取数据也类似

    ForeignKey修改数据

    hosts=models.Host.objects.get(host_name="127.0.0.1")
    users=models.User.objects.get(id=2)
    
    hosts.blong_to=users
    hosts.save()

    反向关联查询

    user_obj=models.User.objects.get(id=2)
    print(user_obj.host_set.select_related())

    ManyToManyField关联

    示例models

    class UserInfo(models.Model):
        name = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
        address = models.CharField(max_length=128)
    
    
    class UserGroup(models.Model):
        caption = models.CharField(max_length=64)
        user_info = models.ManyToManyField('UserInfo')

    ManyToManyField操作(_set是多对多中的固定搭配)

        user_info_obj = models.UserInfo.objects.get(name="zhangsan")
        user_info_objs = models.UserInfo.objects.all()
    
        group_obj = models.UserGroup.objects.get(caption='CEO')
        group_objs = models.UserGroup.objects.all()
    
        # 添加数据
        #group_obj.user_info.add(user_info_obj)
        #group_obj.user_info.add(*user_info_objs)
        #
        #user_info_obj.usergroup_set.add(group_obj)
        #user_info_obj.usergroup_set.add(*group_objs)
    
        # 删除数据
        #group_obj.user_info.remove(user_info_obj)
        #group_obj.user_info.remove(*user_info_objs)
        #
        #user_info_obj.usergroup_set.remove(group_obj)
        #user_info_obj.usergroup_set.remove(*group_objs)
    
        # 获取数据
        #print group_obj.user_info.all()
        #print group_obj.user_info.all().filter(id=1)
        #
        #print user_info_obj.usergroup_set.all()
        #print user_info_obj.usergroup_set.all().filter(caption='CEO')

     F  对同一表内不同的字段进行对比查询

    class Entry(models.Model):
        n_comments = models.IntegerField()
        n_pingbacks = models.IntegerField()
        rating = models.IntegerField()
    from django.db.models import F
    models.Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
    models.Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
    models.Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

    批量自增

    models.Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

     

    Q  构建搜索条件

    from django.db.models import Q
    
    models.UserInfo.objects.get(
        Q(name='zhangsan'),Q(email="12345678@qq.com"))  #两个都要满足
    models.UserInfo.objects.get(
        Q(name='zhangsan') | Q(email="12345678@qq.com"))  #只需满足一个
    models.UserInfo.objects.get(
        Q(name='zhangsan'),Q(email="12345678@qq.com") | Q(address="abcde"))

    django 实现分页

    实例

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from django.shortcuts import render,HttpResponse
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    from app01 import models
    # Create your views here.
    def stu_login(request):
        return render(request,"app01/login.html")
    
    
    def stu_home(request):
        customer_list=models.Customer.objects.all()
        paginator = Paginator(customer_list, 1) #每页显示条数
    
        page = request.GET.get('page')
        try:
            contacts = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            contacts = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            contacts = paginator.page(paginator.num_pages)
    
        return render(request, "app01/home.html", {"customer_list":contacts})
    views
        <div class="pagination">
            <nav>
                <ul class="pagination">
                    {% if customer_list.has_previous %}
                        <li class=""><a href="?page={{ customer_list.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                    {% endif %}
                    {% for page_num in customer_list.paginator.page_range %}
                        {% if page_num == customer_list.number %}<!--如果page_num是当前选中的页-->
                          <li class="active"><a href="?page={{ page_num }}">{{ page_num }} <span class="sr-only">(current)</span></a></li>
                        {% else %}
                          <li class=""><a href="?page={{ page_num }}">{{ page_num }} <span class="sr-only">(current)</span></a></li>
                        {% endif %}
                    {% endfor %}
                    {% if customer_list.has_next %}
                        <li class=""><a href="?page={{ customer_list.next_page_number }}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
                    {% endif %}
                </ul>
            </nav>
        </div>
    html

    优化:固定页码个数

    1、自定义template tags

      

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()
    
    @register.simple_tag
    def custemer_paging(current_page,loop_num): #传入选中页和循环页
        num_left=current_page-2
        num_right=current_page+2
        if loop_num>num_left and loop_num<num_right:#只显示3页
            if current_page == loop_num:
                result='''<li class="active"><a href="?page=%s">%s <span class="sr-only">(current)</span></a></li>'''%(loop_num,loop_num)
            else:
                result='''<li class=""><a href="?page=%s">%s <span class="sr-only">(current)</span></a></li>'''%(loop_num,loop_num)
            return mark_safe(result)
        result=""
        return mark_safe(result)
    custemer_tags.py

    在html开头导入

    {% load custemer_tags %}

    使用自定义simple_tag

        <div class="pagination">
            <nav>
                <ul class="pagination">
                    {% if customer_list.has_previous %}
                        <li class=""><a href="?page={{ customer_list.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                    {% endif %}
                    {% for page_num in customer_list.paginator.page_range %}
                        
                        {% custemer_paging customer_list.number page_num %}<!--使用custemer_tags-->
    
                    {% endfor %}
                    {% if customer_list.has_next %}
                        <li class=""><a href="?page={{ customer_list.next_page_number }}" aria-label="Next"><span aria-hidden="true">&raquo;</span></a></li>
                    {% endif %}
                </ul>
            </nav>
        </div>
    View Code

    更多详情:https://docs.djangoproject.com/en/1.9/topics/pagination/ 

    三、在自己写的脚本里调用django models

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'django_project.settings'
    import django
    django.setup()
    
    from app01 import models
    
    result = models.UserInfo.objects.get(id=1)
    print(result)
    View Code

    四、用户认证

    from django.contrib.auth.models import User
    
    class UserProfile(models.Model):
        user = models.OneToOneField(User)
        name = models.CharField(max_length=32)
    from django.contrib.auth import authenticate,login,logout
    from django.contrib.auth.decorators import login_required
    
    @login_required
    def acc_home(request):
        return render(request,"index.html")
    
    def acc_login(request):
        if request.method == "POST":
            username = request.POST.get("username")
            password = request.POST.get("password")
            user = authenticate(username=username,password=password) #验证
    
            if user is not None:
                login(request,user) #登录
                return redirect("/app01/acc_home/")
        else:
            return render(request,"login.html")
    
    def acc_logout(request):
        logout(request) #退出

    在前端显示用户名或对应的名字

        <div>
            {% if request.user.is_authenticated %} <!--如果已经登录-->
                <span>{{ request.user }}</span> <!--用户名-->
                <span>{{ request.user.userprofile.name }}</span> <!--用户名在UserProfile表对应的名字-->
            {% endif %}
        </div>

    五、权限管理

    django 自带有基本的权限管理 ,但粒度和限制权限的维度都只是针对具体的表

    自己写的权限要易扩展、灵活,权限系统的设计对开发者、用户要实现透明,即他们不需要改变自己原有的使用系统或调用接口的方式,权限要能实现非常小的粒度的控制,甚至细致到一个按键某个用户是否能按。

    想对一个功能实现权限控制,要做到只需在views方法上加一个装饰器就行了

    例:

    在表内创建一个class Meta,自己定义几个权限。

    class UserProfile(models.Model):
        user = models.OneToOneField(User)
        name = models.CharField(verbose_name=u"姓名",max_length=32)
        def __unicode__(self):
            return self.name
        class Meta:
            permissions = (("view_customer_list",u"查看客户信息"),
                           ("view_customer_info",u"查看客户详细信息"),
                           ("view_customer_updata",u"修改详细信息"),
                           )

    python manage.py makemigrations
    python manage.py migrate

    关联动作

    这里创建一个permissions.py,创建check_permission装饰器

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from django.core.urlresolvers import resolve
     4 from django.shortcuts import render
     5 perm_dic = {
     6     "view_customer_list":["customer_list","GET",[]],
     7     "view_customer_info":["customer_info","GET",[]],
     8     "view_customer_updata":["customer_info","POST",[]],
     9 }
    10 
    11 
    12 def perm_check(*args,**kwargs):
    13      request = args[0]
    14      url_resovle_obj = resolve(request.path_info)
    15      current_url_namespace = url_resovle_obj.url_name
    16      #app_name = url_resovle_obj.app_name #use this name later
    17      print("url namespace:",current_url_namespace)
    18      matched_flag = False # find matched perm item
    19      matched_perm_key = None
    20      if current_url_namespace is not None:#if didn't set the url namespace, permission doesn't work
    21          print("find perm...")
    22          for perm_key in perm_dic:
    23              perm_val = perm_dic[perm_key]
    24              if len(perm_val) == 3:#otherwise invalid perm data format
    25                  url_namespace,request_method,request_args = perm_val
    26                  print(url_namespace,current_url_namespace)
    27                  if url_namespace == current_url_namespace: #matched the url
    28                      if request.method == request_method:#matched request method
    29                          if not request_args:#if empty , pass
    30                              matched_flag = True
    31                              matched_perm_key = perm_key
    32                              print('mtched...')
    33                              break #no need looking for  other perms
    34                          else:
    35                              for request_arg in request_args: #might has many args
    36                                  request_method_func = getattr(request,request_method) #get or post mostly
    37                                  #print("----->>>",request_method_func.get(request_arg))
    38                                  if request_method_func.get(request_arg) is not None:
    39                                      matched_flag = True # the arg in set in perm item must be provided in request data
    40                                  else:
    41                                      matched_flag = False
    42                                      print("request arg [%s] not matched" % request_arg)
    43                                      break #no need go further
    44                              if matched_flag == True: # means passed permission check ,no need check others
    45                                  print("--passed permission check--")
    46                                  matched_perm_key = perm_key
    47                                  break
    48 
    49      else:#permission doesn't work
    50          return True
    51 
    52      if matched_flag == True:
    53          #pass permission check
    54          perm_str = "app01.%s" %(matched_perm_key)
    55          if request.user.has_perm(perm_str):
    56              print("33[42;1m--------passed permission check----33[0m")
    57              return True
    58          else:
    59              print("33[41;1m ----- no permission ----33[0m")
    60              print(request.user,perm_str)
    61              return False
    62      else:
    63          print("33[41;1m ----- no matched permission  ----33[0m")
    64 
    65 def check_permission(func):
    66      def wrapper(*args,**kwargs):
    67          print("---start check perms",args[0])
    68          if not perm_check(*args,**kwargs):
    69              return render(args[0],'app01/403.html')
    70          return func(*args,**kwargs)
    71          #print("---done check perms")
    72      return wrapper
    permissions.py
        url(r'^stu_home/$', views.stu_home,name="customer_list"),
        url(r'^stu_detail/(d+)/$', views.stu_detail,name="customer_info"),

    在views导入自己写的装饰器并在相应方法上加一个装饰器

    可以用超级用户通过admin对普通用户进行权限控制

    六、CSRF(跨站域请求伪造)

    CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一

     防御策略

      在请求地址中添加 token 并验证

    Django 中使用CSRF,在表单下使用{% csrf_token %}

    <form action="" method="post">{% csrf_token %}

      

    AJAX中CSRF

    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));
    }
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        }
    });
  • 相关阅读:
    virtualenvwrapper的安装及问题解决
    eclipse添加插件、删除插件 示例: eclipse marketplace
    怎么修改tomcat端口
    Eclipse配置maven环境
    如何查看某个端口被谁占用
    selenium清空默认文字
    Git项目删除文件
    selenium使用chrome抓取自动消失弹框的方法
    Python字符串转为字典方法大全
    接口测试学习
  • 原文地址:https://www.cnblogs.com/melonjiang/p/5565799.html
Copyright © 2011-2022 走看看