django优化和扩展(一)

mysql优化基础

    进行django产品开发或上线以前,有必要了解一下mysql的基础知识,orm太过抽象,致使不少朋友对于mysql了解得太少,并且orm不像sqlalchemy那样能够跟mysql走的那么近!若是要设计出合理的表结构(在orm中就是model类),显然把一个ip设置成64个字符是大大地浪费。本文结合mysql手册,作一些建表优化。python

1、尽量地使用最有效(最小)的数据类型

class Customer(models.Model):
    qq = models.CharField(u"QQ号",max_length=64,unique=True)
    name = models.CharField(u"姓名",max_length=32,blank=True,null=True)
    phone = models.BigIntegerField(u'手机号',blank=True,null=True)
    stu_id = models.CharField(u"学号",blank=True,null=True,max_length=64)

上面这个类从优化角度显然是不合理的,一个qq号占64个字符,姓名32个字符,手机号用的bigint,学号64位,一行数据得占多大空间,下面两张图写明了主要数据类型的区别!mysql

(一)、整形列的应用sql

整形列的选择要慎重,必定要坚持最小化的原则,并且必定要选择无符号的整数,在orm无符号的声明以下:django

class cj_user(models.Model):
    cjid = models.PositiveIntegerField() # Positive 开头通常都是无符号


# 在声明非主键字段时能够如上应用,若是优化主键,必须重写AutoField,由于orm默认生成的是int类型,且是有符号的,优化方法能够参照我最后写的

(二)、char、varchar、text的区别mysql优化

讲以前问2个问题:app

1,char(5)和varchar(5) 能不能存下'abcdefg'?dom

2,char(5)和varchar(20)一样存'abcd'各占几个字符?几个字节?oop

()中的数字都是字符数,若是要算字节数必须utf-8*3 gbk*2,但varchar是变长,内容多少就占多少,他有一点比较特殊,varchar(20)存'abc'的时候占4个字符,由于在末尾加\0优化

在工做中应尽可能使用定长,如char和上面的整形列 都是定长,有利加速,变长一般用一对一的形式存在附加表中,也能够综合应用,但最佳的优化仍是分表存储!手机,身份证、姓名、密码都是比较固定的字段,如密码,不管设几位,最后都会被加密成32位字符串!如下是个人用户表( FixCharField是我自定义的char,由于在orm中不支持char,CharField生成的是varchar变长类型。在本文的最后我会讲一下,如何自定义!)加密

class hwj_user(models.Model):
    xm = FixCharField(max_length=4)
    tel = FixCharField(max_length=11)
    sfz = FixCharField(max_length=18)
    pwd = FixCharField(max_length=32)

注:varchar(max)的单位是字节即最多存65535个字节,以utf-8为例,约2万多个汉字!

(三)主键和非空字段要用not null

手册上说:若是可能,声明列为NOT NULL。它使任何事情更快并且每列能够节省一位。这点orm中已经默认这么干了,固然这里也建议你不要把

null=True写上去

2、慎用索引

索引是会加快速度,但我觉除了主键、多对多的表没法避免外,其余都要慎用,由于索引会加快查询速度,却会下降写入速度,若是你的表有相似频繁写入的功能,如抢购等,那你就不要使用,像惟一这种都属于索引,尽可能在业务中去判断他是否存在。

3、多设默认值

默认值的设置也是优化的一方面,也能使数据层避免产生错误,即使是not null的列,也应该给他设上default='',数值类型default=0等等!

4、随机排序的实现

因为orm不支持随机排序,若是要实现数据的随机排机,只能借助于python(也能够重写oder_by但太复杂了)

   ids = models.Tk.objects.filter(eid_id=exam_data.id).all().values('id')
    rand_id=[]
    for id in ids:
        rand_id.append(id["id"])
    rand_num = random.sample(rand_id,5)
    print(rand_num)
    tks = models.Tk.objects.filter(eid_id=exam_data.id,id__in=rand_num).all()

1,先取出全部的id,把他们放到列表

2,利用random.sample 在列中随机选择5个id

3,利用orm的id__in过滤出id所在行的记录

5、自定义数据类型

class FixCharField(models.Field):
    def __init__(self, *args, **kwargs):
        super(FixCharField, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'char(%s)' % self.max_length


class hwj(models.Model):
    my_field = FixCharField(max_length=25)

只是重写了,具体可看django源码

6、模板中的计数 上层循环计数

有的时候要输出上层循环的计数值,在相关书籍上也只看到当前循环{{ forloop.counter }},看了底层才知道还有forloop.parentloop.counter

以向是我模板中用反向查找实现了在题目下显示题目的方法,用嵌套循环实现的!

    {% for o in tks %}
    <div class="panel panel-info">
  <!-- Default panel contents -->
  <div class="panel-heading" name="ks{{ o.attr }}">{{ forloop.counter }}、{{ o.subject }}</div>
  <div class="panel-body">

     {% for i in o.op_set.all %}

  <p><input type="radio" name="dx{{ forloop.parentloop.counter }}" title="{{o.answer}}"  class="option-input radio" value="{{i.opstr}}"> {{i.opstr}} {{i.opname}}</p>
  <p style="padding:0; margin:0; height:5px;"></p>
{% endfor %}

立刻开会了,今天就写到这里。

相关文章
相关标签/搜索