zoukankan      html  css  js  c++  java
  • Django-模板系统、session、web框架、内置分页

    模板系统

    模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。

    模板中也有自己的语言,该语言可以实现数据展示

    {{ item }}
    {% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
      forloop.counter
      forloop.first
      forloop.last 
    {% if ordered_warranty %}  {% else %} {% endif %}
    母板:{% block title %}{% endblock %}
    子板:{% extends "base.html" %}
       {% block title %}{% endblock %}
    帮助方法:
    {{ item.event_start|date:"Y-m-d H:i:s"}}
    {{ bio|truncatewords:"30" }}
    {{ my_list|first|upper }}
    {{ name|lower }}
    

    自定义simple_tag:

    a、在app中创建templatetags模块

    b、创建任意 .py 文件,如:xx.py

    from django import template
    from django.utils.safestring import mark_safe
       
    register = template.Library()
    
    @register.filter()
    def my_upper(val, args):
        return val + args
    
    @register.simple_tag
    def my_simple_time(v1,v2,v3):
        return  v1 + v2 + v3
       
    @register.simple_tag
    def my_input(id,arg):
        result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
        return mark_safe(result)
    

    c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

    {% load xx %}
    

    d. 使用simple_tag

    {% my_simple_time 1 2 3%}
    {% my_input 'id_username' 'hide'%}
    

    e、在settings中配置当前app,不然django无法找到自定义的simple_tag  

    session

    Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

    • 数据库(默认)
    • 缓存
    • 文件
    • 缓存+数据库
    • 加密cookie

    1、数据库Session

    Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
     
     
     
    b. 使用
     
        def index(request):
            # 获取、设置、删除Session中数据
            request.session['k1']
            request.session.get('k1',None)
            request.session['k1'] = 123
            request.session.setdefault('k1',123) # 存在则不设置
            del request.session['k1']
     
            # 所有 键、值、键值对
            request.session.keys()
            request.session.values()
            request.session.items()
            request.session.iterkeys()
            request.session.itervalues()
            request.session.iteritems()
     
     
            # 用户session的随机字符串
            request.session.session_key
     
            # 将所有Session失效日期小于当前日期的数据删除
            request.session.clear_expired()
     
            # 检查 用户session的随机字符串 在数据库中是否
            request.session.exists("session_key")
     
            # 删除当前用户的所有Session数据
            request.session.delete("session_key")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    

    2、缓存Session

    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
        SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
     
     
        SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
     
     
     
    b. 使用
     
        同上
    

    3、文件Session

    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
        SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
     
     
        SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
     
    b. 使用
     
        同上
    

    4、缓存+数据库Session

    数据库用于做持久化,缓存用于提高效率
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
     
    b. 使用
     
        同上
    

    5、加密cookie Session

    a. 配置 settings.py
         
        SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
     
    b. 使用
     
        同上
    

    模型操作

    到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

    • 创建数据库,设计表结构和字段
    • 使用 MySQLdb 来连接数据库,并编写数据访问层代码
    • 业务逻辑层去调用数据访问层执行数据库操作
    import MySQLdb
     
    def GetList(sql):
        db = MySQLdb.connect(user='root', db='test', passwd='1234', host='localhost')
        cursor = db.cursor()
        cursor.execute(sql)
        data = cursor.fetchall()
        db.close()
        return data
     
    def GetSingle(sql):
        db = MySQLdb.connect(user='root', db='test', passwd='1234', host='localhost')
        cursor = db.cursor()
        cursor.execute(sql)
        data = cursor.fetchone()
        db.close()
        return data
    

    django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

    • PHP:activerecord
    • Java:Hibernate
    • C#:Entity Framework

    django中遵循 Code Frist的原则,即:根据代码中定义的类来自动生成数据库表。

    Django的配置:

    'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 's2day19',    ## 数据库名称
            'USER': 'root',
            'PASSWORD': '123qwe',    ## 安装 mysql 数据库时,输入的 root 用户的密码
            'HOST': '127.0.0.1',
        }
    

    一、创建表

    1、基本结构

    from django.db import models
      
    class userinfo(models.Model):
        name = models.CharField(max_length=30)
        email = models.EmailField()
        memo = models.TextField()
    

    2、字段

    AutoField(Field)
            - int自增列,必须填入参数 primary_key=True
    
    BigAutoField(AutoField)
            - bigint自增列,必须填入参数 primary_key=True
    
            注:当model中如果没有自增列,则自动会创建一个列名为id的列
            from django.db import models
    
            class UserInfo(models.Model):
                # 自动创建一个列名为id的且为自增的整数列
                username = models.CharField(max_length=32)
    
            class Group(models.Model):
                # 自定义自增列
                nid = models.AutoField(primary_key=True)
                name = models.CharField(max_length=32)
    
        SmallIntegerField(IntegerField):
            - 小整数 -32768 ~ 32767
    
        PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正小整数 0 ~ 32767
        IntegerField(Field)
            - 整数列(有符号的) -2147483648 ~ 2147483647
    
        PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
            - 正整数 0 ~ 2147483647
    
        BigIntegerField(IntegerField):
            - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
    
        自定义无符号整数字段
    
            class UnsignedIntegerField(models.IntegerField):
                def db_type(self, connection):
                    return 'integer UNSIGNED'
    
            PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
                'AutoField': 'integer AUTO_INCREMENT',
                'BigAutoField': 'bigint AUTO_INCREMENT',
                'BinaryField': 'longblob',
                'BooleanField': 'bool',
                'CharField': 'varchar(%(max_length)s)',
                'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
                'DateField': 'date',
                'DateTimeField': 'datetime',
                'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
                'DurationField': 'bigint',
                'FileField': 'varchar(%(max_length)s)',
                'FilePathField': 'varchar(%(max_length)s)',
                'FloatField': 'double precision',
                'IntegerField': 'integer',
                'BigIntegerField': 'bigint',
                'IPAddressField': 'char(15)',
                'GenericIPAddressField': 'char(39)',
                'NullBooleanField': 'bool',
                'OneToOneField': 'integer',
                'PositiveIntegerField': 'integer UNSIGNED',
                'PositiveSmallIntegerField': 'smallint UNSIGNED',
                'SlugField': 'varchar(%(max_length)s)',
                'SmallIntegerField': 'smallint',
                'TextField': 'longtext',
                'TimeField': 'time',
                'UUIDField': 'char(32)',
    
        BooleanField(Field)
            - 布尔值类型
    
        NullBooleanField(Field):
            - 可以为空的布尔值
    
        CharField(Field)
            - 字符类型
            - 必须提供max_length参数, max_length表示字符长度
    
        TextField(Field)
            - 文本类型
    
        EmailField(CharField):
            - 字符串类型,Django Admin以及ModelForm中提供验证机制
    
        IPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
    
        GenericIPAddressField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
            - 参数:
                protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
                unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
    
        URLField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证 URL
    
        SlugField(CharField)
            - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    
        CommaSeparatedIntegerField(CharField)
            - 字符串类型,格式必须为逗号分割的数字
    
        UUIDField(Field)
            - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    
        FilePathField(Field)
            - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
            - 参数:
                    path,                      文件夹路径
                    match=None,                正则匹配
                    recursive=False,           递归下面的文件夹
                    allow_files=True,          允许文件
                    allow_folders=False,       允许文件夹
    
        FileField(Field)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    
        ImageField(FileField)
            - 字符串,路径保存在数据库,文件上传到指定目录
            - 参数:
                upload_to = ""      上传文件的保存路径
                storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
                width_field=None,   上传图片的高度保存的数据库字段名(字符串)
                height_field=None   上传图片的宽度保存的数据库字段名(字符串)
    
        DateTimeField(DateField)
            - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
    
        DateField(DateTimeCheckMixin, Field)
            - 日期格式      YYYY-MM-DD
    
        TimeField(DateTimeCheckMixin, Field)
            - 时间格式      HH:MM[:ss[.uuuuuu]]
    
        DurationField(Field)
            - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
    
        FloatField(Field)
            - 浮点型
    
        DecimalField(Field)
            - 10进制小数
            - 参数:
                max_digits,小数总长度
                decimal_places,小数位长度
    
        BinaryField(Field)
            - 二进制类型
    

    3、参数

    null                数据库中字段是否可以为空
        db_column           数据库中字段的列名
        db_tablespace
        default             数据库中字段的默认值
        primary_key         数据库中字段是否为主键
        db_index            数据库中字段是否可以建立索引
        unique              数据库中字段是否可以建立唯一索引
        unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
        unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
        unique_for_year     数据库中字段【年】部分是否可以建立唯一索引
    
        verbose_name        Admin中显示的字段名称
        blank               Admin中是否允许用户输入为空
        editable            Admin中是否可以编辑
        help_text           Admin中该字段的提示信息
        choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
                            如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
    
        error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
                            字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                            如:{'null': "不能为空.", 'invalid': '格式错误'}
    
        validators          自定义错误验证(列表类型),从而定制想要的验证规则
                            from django.core.validators import RegexValidator
                            from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
                            MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                            如:
                                test = models.CharField(
                                    max_length=32,
                                    error_messages={
                                        'c1': '优先错信息1',
                                        'c2': '优先错信息2',
                                        'c3': '优先错信息3',
                                    },
                                    validators=[
                                        RegexValidator(regex='root_d+', message='错误了', code='c1'),
                                        RegexValidator(regex='root_112233d+', message='又错误了', code='c2'),
                                        EmailValidator(message='又错误了', code='c3'), ]
                                )
    

    4、连表操作

    • 一对多:models.ForeignKey(其他表)
    • 多对多:models.ManyToManyField(其他表)
    • 一对一:models.OneToOneField(其他表)
    应用场景:
    
    一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
    例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
    多对多:在某表中创建一行数据是,有一个可以多选的下拉框
    例如:创建用户信息,需要为用户指定多个爱好
    一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
    例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
    

    二、操作表的方式

    1、基本操作

    # 增
    #
    # models.Tb1.objects.create(c1='xx', c2='oo')  增加一条数据,可以接受字典类型数据 **kwargs
    
    # obj = models.Tb1(c1='xx', c2='oo')
    # obj.save()
    
    # 查
    #
    # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
    # models.Tb1.objects.all()               # 获取全部
    # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据
    
    # 删
    #
    # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据
    
    # 改
    # models.Tb1.objects.filter(name='seven').update(gender='0')  # 将指定条件的数据更新,均支持 **kwargs
    # obj = models.Tb1.objects.get(id=1)
    # obj.c1 = '111'
    # obj.save()                                                 # 修改单条数据
    

    2、进阶操作

    # 获取个数
    #
    # models.Tb1.objects.filter(name='seven').count()
    
    # 大于,小于
    #
    # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
    # models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值
    # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
    # models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值
    # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
    
    # in
    #
    # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
    # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
    
    # isnull
    # Entry.objects.filter(pub_date__isnull=True)
    
    # contains
    #
    # models.Tb1.objects.filter(name__contains="ven")
    # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
    # models.Tb1.objects.exclude(name__icontains="ven")
    
    # range
    #
    # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
    
    # 其他类似
    #
    # startswith,istartswith, endswith, iendswith,
    
    # order by
    #
    # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
    # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc
    
    # group by
    #
    # from django.db.models import Count, Min, Max, Sum
    # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
    # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
    
    # limit 、offset
    #
    # models.Tb1.objects.all()[10:20]
    
    # date
    #
    # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
    # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
    
    # year
    #
    # Entry.objects.filter(pub_date__year=2005)
    # Entry.objects.filter(pub_date__year__gte=2005)
    
    # month
    #
    # Entry.objects.filter(pub_date__month=12)
    # Entry.objects.filter(pub_date__month__gte=6)
    
    # day
    #
    # Entry.objects.filter(pub_date__day=3)
    # Entry.objects.filter(pub_date__day__gte=3)
    
    # week_day
    #
    # Entry.objects.filter(pub_date__week_day=2)
    # Entry.objects.filter(pub_date__week_day__gte=2)
    
    # hour
    #
    # Event.objects.filter(timestamp__hour=23)
    # Event.objects.filter(time__hour=5)
    # Event.objects.filter(timestamp__hour__gte=12)
    
    # minute
    #
    # Event.objects.filter(timestamp__minute=29)
    # Event.objects.filter(time__minute=46)
    # Event.objects.filter(timestamp__minute__gte=29)
    
    # second
    #
    # Event.objects.filter(timestamp__second=31)
    # Event.objects.filter(time__second=2)
    # Event.objects.filter(timestamp__second__gte=31)
    

    2.1 高级操作

        # extra
        #
        # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
        #    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
        #    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
        #    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
        #    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
    
        # F
        #
        # from django.db.models import F
        # models.Tb1.objects.update(num=F('num')+1)
    
    
        # Q
        #
        # 方式一:
        # Q(nid__gt=10)
        # Q(nid=8) | Q(nid__gt=10)
        # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
    
        # 方式二:
        # con = Q()
        # q1 = Q()
        # q1.connector = 'OR'
        # q1.children.append(('id', 1))
        # q1.children.append(('id', 10))
        # q1.children.append(('id', 9))
        # q2 = Q()
        # q2.connector = 'OR'
        # q2.children.append(('c1', 1))
        # q2.children.append(('c1', 10))
        # q2.children.append(('c1', 9))
        # con.add(q1, 'AND')
        # con.add(q2, 'AND')
        #
        # models.Tb1.objects.filter(con)
    
    
        # 执行原生SQL
        #
        # from django.db import connection, connections
        # cursor = connection.cursor()  # cursor = connections['default'].cursor()
        # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
        # row = cursor.fetchone()
    
    其他操作
    

    3、一对一操作

    # 一对多的添加
    # models.students.objects.create(stuname='二狗子', classid_id=2)
    # models.students.objects.create(stuname='狗剩子', classid_id=1)
    # models.students.objects.create(stuname='铁蛋', classid_id=2)
    # models.students.objects.create(stuname='王钢蛋', classid_id=3)
    # models.students.objects.create(stuname='铁锤', classid_id=1)
    
    # 一对多的查询 classid为FK字段 正向操作
    # res = models.students.objects.all()
    #
    # for item in res:
    #     print(item.id, item.stuname, item.classid_id, item.classid.classname)
    
    
    # 反向操作
    # obj.小写表名_set.all()
    # res = models.classes.objects.filter(classname='周末一期').first()
    # print(res.id, res.classname)
    #
    # info = (res.students_set.all())
    #
    # for item in info:
    #     print(item.stuname)
    
    # 获取特定的字段 values() 和 values_list() 以及神奇的双下划线
    # res = models.classes.objects.all().values('classname')
    # print(res)
    # for item in res:
    #     print(item['classname'])
    
    # res = models.students.objects.all().values_list('stuname', 'classid_id', 'classid__classname')
    # print(res)
    
    # res = models.students.objects.filter(classid__classname='周末一期')
    # print(res)
    # for item in res:
    #     print(item.stuname)
    

    4、多对多操作

    user_info_obj = models.UserInfo.objects.get(name=u'xxx')
    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)
     
    # 删除数据
    #group_obj.user_info.remove(user_info_obj)
    #group_obj.user_info.remove(*user_info_objs)
     
    # 添加数据
    #user_info_obj.usergroup_set.add(group_obj)
    #user_info_obj.usergroup_set.add(*group_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')
    #print user_info_obj.usergroup_set.all().filter(caption='DBA')
    

    自定义web框架

    from wsgiref.simple_server import make_server
    
    
    def index():
        return [b'index',]
    
    
    def login():
        return [b'login',]
    
    
    def routers():
        urlpatterns = (
            ('/index/', index),
            ('/login/', login),
        )
    
        return urlpatterns
    
    
    def RunServer(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        url = environ['PATH_INFO']
        urlpatterns = routers()
        func = None
        for item in urlpatterns:
            if item[0] == url:
                func = item[1]
                break
        if func:
            return func()
        else:
            return [b'404 not found',]
    
    
    if __name__ == '__main__':
        httpd = make_server('', 8011, RunServer)
        print("Serving HTTP on port 8000...")
        httpd.serve_forever()
    - 开启全局的csrf验证
            1. settings中,打开注释 'django.middleware.csrf.CsrfViewMiddleware',
            2. 表单中,开启csrf_token
                <form>
                    {% csrf_token %}
                    <input type='text'>
                </form>
            如上, 全站都会进行csrf验证
    
        - 开启全局的csrf,但是部分业务函数不进行检验
            1. settings中,打开注释 ====》'django.middleware.csrf.CsrfViewMiddleware',
            2. views中,引入如下函数
                from django.views.decorators.csrf import csrf_exempt
                @csrf_exempt
                def csrf1(request):
                    if request.method == 'GET':
                        return render(request, 'csrf1.html')
                    else:
                        return HttpResponse('ok')
            如上, 即便全局开启验证,但是可以使用装饰器进行特殊处理,不使用
    
        - 关闭全局的csrf, 但是部分业务函数要使用csrf验证
            1. settings中,注释 ===》 #'django.middleware.csrf.CsrfViewMiddleware',
            2. views中,引入如下函数
                from django.views.decorators.csrf import csrf_protect
                @csrf_protect
                def csrf1(request):
                    if request.method == 'GET':
                        return render(request, 'csrf1.html')
                    else:
                        return HttpResponse('ok')
    
        若是CBV:
            from django.utils.decorators import method_decorator
            @method_decorator(csrf_protect, name='get')
            class User(View):
                def get(self, request):
                    pass
    
                def post(self, request):
                    pass
    
        ajax方式提交数据:
    
             将token放置到请求头中, 携带过来
    
                headers : {'X-CSRFToken': token}
    

    Form组件

    创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

    1、Django内置字段如下:

    Field
        required=True,               是否允许为空
        widget=None,                 HTML插件
        label=None,                  用于生成Label标签或显示内容
        initial=None,                初始值
        help_text='',                帮助信息(在标签旁边显示)
        error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
        validators=[],               自定义验证规则
        localize=False,              是否支持本地化
        disabled=False,              是否可以编辑
        label_suffix=None            Label内容后缀
     
     
    CharField(Field)
        max_length=None,             最大长度
        min_length=None,             最小长度
        strip=True                   是否移除用户输入空白
     
    IntegerField(Field)
        max_value=None,              最大值
        min_value=None,              最小值
     
    FloatField(IntegerField)
        ...
     
    DecimalField(IntegerField)
        max_value=None,              最大值
        min_value=None,              最小值
        max_digits=None,             总长度
        decimal_places=None,         小数位长度
     
    BaseTemporalField(Field)
        input_formats=None          时间格式化   
     
    DateField(BaseTemporalField)    格式:2015-09-01
    TimeField(BaseTemporalField)    格式:11:12
    DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
     
    DurationField(Field)            时间间隔:%d %H:%M:%S.%f
        ...
     
    RegexField(CharField)
        regex,                      自定制正则表达式
        max_length=None,            最大长度
        min_length=None,            最小长度
        error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
     
    EmailField(CharField)      
        ...
     
    FileField(Field)
        allow_empty_file=False     是否允许空文件
     
    ImageField(FileField)      
        ...
        注:需要PIL模块,pip3 install Pillow
        以上两个字典使用时,需要注意两点:
            - form表单中 enctype="multipart/form-data"
            - view函数中 obj = MyForm(request.POST, request.FILES)
     
    URLField(Field)
        ...
     
     
    BooleanField(Field)  
        ...
     
    NullBooleanField(BooleanField)
        ...
     
    ChoiceField(Field)
        ...
        choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
        required=True,             是否必填
        widget=None,               插件,默认select插件
        label=None,                Label内容
        initial=None,              初始值
        help_text='',              帮助提示
     
     
    ModelChoiceField(ChoiceField)
        ...                        django.forms.models.ModelChoiceField
        queryset,                  # 查询数据库中的数据
        empty_label="---------",   # 默认空显示内容
        to_field_name=None,        # HTML中value的值对应的字段
        limit_choices_to=None      # ModelForm中对queryset二次筛选
         
    ModelMultipleChoiceField(ModelChoiceField)
        ...                        django.forms.models.ModelMultipleChoiceField
     
     
         
    TypedChoiceField(ChoiceField)
        coerce = lambda val: val   对选中的值进行一次转换
        empty_value= ''            空值的默认值
     
    MultipleChoiceField(ChoiceField)
        ...
     
    TypedMultipleChoiceField(MultipleChoiceField)
        coerce = lambda val: val   对选中的每一个值进行一次转换
        empty_value= ''            空值的默认值
     
    ComboField(Field)
        fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                                   fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
     
    MultiValueField(Field)
        PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
     
    SplitDateTimeField(MultiValueField)
        input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
        input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
     
    FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
        path,                      文件夹路径
        match=None,                正则匹配
        recursive=False,           递归下面的文件夹
        allow_files=True,          允许文件
        allow_folders=False,       允许文件夹
        required=True,
        widget=None,
        label=None,
        initial=None,
        help_text=''
     
    GenericIPAddressField
        protocol='both',           both,ipv4,ipv6支持的IP格式
        unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
     
    SlugField(CharField)           数字,字母,下划线,减号(连字符)
        ...
     
    UUIDField(CharField)           uuid类型
        ...
    

    views.py

    from django.forms import Form
    from django.forms import fields
    from django.forms import Widget,PasswordInput
    
    class LoginForm(Form):
        username = fields.CharField(
            required=True,
    
            # label='用户名',
            # initial=666,
            # help_text='帮助信息',
            # # disabled=True,
            # label_suffix='--->',
    
            max_length=18,
            min_length=6,
            error_messages={
                'required' : '用户名不能为空',
                'max_length': '用户名不能超过18',
                'min_length': '用户名最小为6',
            }
        )
    
        # password = fields.IntegerField(
        #     required=True,
        #     max_value=99999999,
        #     min_value=100000,
        #     error_messages={
        #         'required' : '密码不能为空',
        #         'invalid'  :  '格式不正确',
        #         'min_value': '密码最少六位',
        #         'max_value': '密码最多12位',
        #     },
        #     # widget=PasswordInput
        # )
    
        email = fields.EmailField()
    
    
    
    def login(request):
    
        if request.method == 'GET':
            obj = LoginForm()
            print(obj)
    
            return render(request, 'login.html', {'obj':obj})
        else:
            # username = request.POST.get('username')
            # print(username)
            obj = LoginForm(request.POST)
    
            if obj.is_valid():
                print(obj.cleaned_data)
            else:
                errors = obj.errors
                # <ul class="errorlist">
                #   <li>username
                #       <ul class="errorlist">
                #           <li>This field is required.</li>
                #       </ul>
                #   </li>
                # </ul>
    
                # print(type(errors))
                # print(errors)
    
            return render(request, 'login.html', {'obj' : obj})
    

    Django内置分页

    views.py

    def user(request):
    
        # for i in range(300):
        #
        #     username = 'root' + str(i)
        #
        #     models.UserInfo.objects.create(username=username, nickname=username, gender=1, age=23)
    
        from django.core.paginator import Paginator
    
        cur_page = request.GET.get('cur_page')
        print(cur_page)
    
        res = models.UserInfo.objects.all()
    
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        paginator = Paginator(res, 10)
    
        print(paginator)
    
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
        info = paginator.page(cur_page)
    
        return render(request, 'user.html', {'info':info})
    

    user.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h3>信息如下</h3>
    
    <ul>
        {% for item in info.object_list %}
            <li>
                {{ item.username }}
            </li>
        {% endfor %}
    </ul>
    
    <div>
    
         {% if info.has_previous %}
            <a href="/user/?cur_page={{ info.previous_page_number }}">上一页</a>
        {% endif %}
    
        {% for item in info.paginator.page_range %}
            <a href="/user/?cur_page={{ item }}">{{ item }}</a>
        {% endfor %}
    
    
        {% if info.has_next %}
            <a href="/user/?cur_page={{ info.next_page_number }}">下一页</a>
        {% endif %}
    
    
    </div>
    
    </body>
    </html>
    

    自定义分页

    class PageInfo(object):
    
        def __init__(self, cur_page, total, per_page, show_page=11):
            '''
            :param cur_page: 当前第几页
            :param total: 总共多少数据
            :param per_page: 每页多少条数据
            '''
    
            try:
                self.cur_page = int(cur_page)
            except Exception as e:
                self.cur_page = 1
    
            self.per_page = per_page
            self.show_page = show_page
    
            a,b = divmod(total, self.per_page)
            if b:
                self.total_page_num = a + 1
            else:
                self.total_page_num = a
    
        def start(self):
    
            return (self.cur_page - 1) * self.per_page
    
        def end(self):
    
            return self.cur_page * self.per_page
    
        def pager(self):
    
            page_list = []
    
            half = int((self.show_page - 1) / 2)
    
            # 上一页
            if self.cur_page == 1:
                prev_page = "<a class='page' href='#'>上一页</a>"
            else:
                prev_page = "<a class='page' href='/custom/?cur_page=%s'>上一页</a>" % (self.cur_page - 1,)
            page_list.append(prev_page)
    
    
            # 当总页数少于11页的时候,显示所有的
            if self.total_page_num <= self.show_page:
                begin = 1
                end = self.total_page_num + 1
            else:
    
                # 当前页 <= 5时, 做处理
                if self.cur_page <= half:
                    begin = 1
                    end = self.show_page + 1
                elif self.cur_page + half >= self.total_page_num:
                    begin = self.cur_page - half
                    end = self.total_page_num + 1
                else:
                    begin = self.cur_page - half
                    end = self.cur_page + half + 1
    
    
    
            for i in range(begin, end):
    
                if i == self.cur_page:
                    v = "<a class='page active' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
                else:
                    v = "<a class='page' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
                page_list.append(v)
    
    
            if self.cur_page == self.total_page_num:
                next_page = "<a class='page' href='#'>下一页</a>"
            else:
                next_page = "<a class='page' href='/custom/?cur_page=%s'>下一页</a>" % (self.cur_page + 1,)
            page_list.append(next_page)
    
            return ' '.join(page_list)
    

    django request.POST和request.body获取值时出现的情况

    django request.POST / request.body
        当request.POST没有值 需要考虑下面两个要求
            1.如果请求头中的: Content-Type: application/x-www-form-urlencoded   request.POST中才会有值(才会去request.body中解析数据)
            2.若1有,也不一定有值 必须有数据格式要求: name=alex&age=18&gender=男
    
    
        如:
            a. form表单提交 默认就会满足上诉的1和2
                <form method...>
                    input
                </form>
    
            b. ajax提交
                $.ajax({
                    url:...
                    type:POST,
                    data:{
                        name:alex,
                        age=18,
                    }     #默认也会满足上诉1和2  请求头默认为上述情况 内部数据格式会转为上述情况
                })
    
               自定义ajax 情况一
               $.ajax({
                    url:...
                    type:POST,
                    headers:{'Content-Type':"application/json"}  #不同的请求头 导致request.POST获取不了数据 而request.body依旧存在数据
                    data:{name:alex, age = 18}   #内部自动转换 name=alex&age=18
    
               }) #即body有值 POST无值
    
               自定义ajax 情况二
               $.ajax({
                    url:...
                    type:POST,
                    headers:{'Content-Type':"application/json"}  #不同的请求头 导致request.POST获取不了数据 而request.body依旧存在数据
                    data:JSON.stringfy{name:alex, age = 18} #{name:alex,age:18}
    
               })  #body有值 POST无值
               #从 request.body里获取数据 然后再通过json.loads(request.body)
    
  • 相关阅读:
    Server Apache Tomcat v7.0 at localhost failed to start.
    iOS-UITextField、一些知识点
    iOS-UIButton
    iOS-URL
    iOS-UITableView(三)
    iOS-MVC(转)
    iOS-UITableView(二)
    iOS-UITableView(一)
    iOS-UIScrollView以及代理
    iOS-UIView常见方法、xib的基本使用
  • 原文地址:https://www.cnblogs.com/gaohuayan/p/11370859.html
Copyright © 2011-2022 走看看