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 %}

立刻開會了,今天就寫到這裏。

相關文章
相關標籤/搜索