Django-- CRM1客戶建表與裝飾器

1、CRM項目(1)

  引入三個表:用戶表,客戶表,校區表,班級表,梳理邏輯關係並遷移數據庫,生成表。javascript

  使用admin插入數據,admin是Django提供的web形式的後臺數據管理頁面,它是和用戶認證組件相通的,使用超級用戶便可登陸admin後臺,並管理本身的數據庫。java

  作出所有客戶列表頁面和個人客戶列表頁面。python

2、裝飾器

  在python中,裝飾器以及前面講到的迭代器,生成器都是十二分重要的高級函數。要想理解裝飾器,首先要掌握如下幾點準備知識:web

一、準備一:回顧並理解做用域的相關知識

二、準備二:函數即對象

    在python的世界裏,函數和咱們以前的[1,2,3],'abc',8等同樣都是對象,並且函數是最高級的對象(對象是類的實例化,能夠調用相應的方法,函數是包含變量對象的對象)數據庫

def foo():
      print('i am the foo')
      bar()
     
  def bar():     
      print('i am the bar')
 
  foo()
  # def bar():      # bar函數定義放到foo()後邊會報錯
  #     print('i am the bar')

帶着上面的問題,咱們看看函數在內存的存儲狀況,以下圖:django

    既然函數是對象,那麼天然知足下面兩個條件:函數對象的調用僅僅比其餘對象多了一個()而已!foo,bar與a,b同樣都是個變量名。那麼上面示例的報錯問題也就解決了,由於只有函數加載到內存才能夠被調用。編程

    1)函數能夠被賦給其餘變量緩存

def foo():
      print('foo')
  bar=foo
  bar()
  foo()
  print(id(foo),id(bar))  #4321123592 4321123592

 

    2)函數能夠被定義在另一個函數內(做爲參數&做爲返回值),相似於整型,字符串等對象閉包

#*******函數名做爲參數**********
  def foo(func):
      print('foo')
      func()
 
  def bar():
      print('bar')
 
  foo(bar)
 
  #*******函數名做爲返回值*********
  def foo():
      print('foo')
      return bar
 
  def bar():
      print('bar')
 
  b=foo()
  b()

   注意:這裏說的函數都是指函數名,好比foo;而foo()表示已經執行函數了,foo()是什麼類型取決於return的內容是什麼類型!!!另外,若是你理解不了對象,那麼就將函數理解成變量,由於函數對象總會由一個或多個變量引用,好比foo,bar。app

三、準備三:函數的嵌套以及閉包

    python容許建立嵌套函數,經過在函數內部def的關鍵字再聲明一個函數即爲嵌套。先看下面這個函數嵌套的示例,分析可否正常執行:

def foo():
      print('foo')
      def bar():
          print('bar')
      # bar()    
  bar()   # 報錯緣由:找不到這個引用變量
  # 分析:沒錯,bar就是一個變量名,有本身的做用域的,所以bar()不能執行。

  再看下面一個函數嵌套的示例,並思考執行inner函數的兩種方法有什麼區別:

def outer():
    x = 1
    def inner():
      print (x)  
    # inner()  # 方式一
    return inner  # 方式二
 
  # outer()  # 方式一
  in_func=outer()   # 方式二:這裏其實就是一個變量賦值,將inner的引用對象賦值給in_func,相似於a=5,b=a同樣
  in_func()

   分析:兩種調用方式有區別嗎,不都是在外面調用inner嗎?按照方式二調用後,inner()已經加載到內存了!

    回顧閉包的概念:若是在一個內部函數裏,對在外部做用域(但不是在全局做用域)的變量進行引用,那麼內部函數就被認爲是閉包(closure)。

    如上示例,inner就是內部函數,inner裏引用了外部做用域的變量x(x在外部做用域outer裏面,不是全局做用域),則這個內部函數inner就是一個閉包。

四、裝飾器的概念

    說了這麼多,終於到裝飾器了。裝飾器本質上是一個函數,該函數用來處理其餘函數,它可讓其餘函數在不須要修改代碼的前提下增長額外的功能,裝飾器的返回值也是一個函數對象。它常常用於有切面需求的場景,好比:插入日誌、性能測試、事務處理、緩存、權限校驗等應用場景。裝飾器是解決這類問題的絕佳設計,有了裝飾器,咱們就能夠抽離出大量與函數功能自己無關的雷同代碼並繼續重用。歸納的講,裝飾器的做用就是爲已經存在的對象添加額外的功能。

    好比,業務生產中有以下一個大量調用的函數:

 def add():
      for i in range(30000000):
          ret+=i
      print(ret)
  add()

如今有一個新的需求,但願能夠記錄下函數的執行時間,因而在函數中添加日誌代碼:

  總結:雖然實現了需求,可是這樣作違反了開發的開放封閉原則的封閉原則,即不要輕易去改已經寫好方法!並且若是要給其餘函數也要加記錄時間的代碼,再用以上方法會形成代碼冗餘,因此想想有沒有其餘方法。你可能會想到單獨定義一個記錄時間的函數,以下:

import time
  def show_time(func):
      start_time=time.time()
      func()
      end_time=time.time()
      print('spend %s'%(end_time-start_time))
 
  def add():
      for i in range(30000000):
          ret+=i
      print(ret)
 
  show_time(add)

上面示例從邏輯上不難理解,並且運行正常。可是這樣的話,以前執行業務邏輯時,執行運行add(),可是如今不得不改爲show_time(add),這種方式就違反了開發的開放封閉原則的開放原則,即不要改動以前已有的調用方式。那麼有沒有更好的方式的呢?固然有,答案就是裝飾器。 

五、簡單裝飾器

    若是,能夠將上例中的add()=show_time(add),那麼就能夠在不違反開放封閉原則前提下完成需求了,因此,咱們須要show_time(add)返回一個函數對象,而這個函數對象內則是核心業務函數:執行func()與裝飾函數時間計算,修改以下:

import time
 
  def show_time(func):
        def inner():
            start_time=time.time()
            func()
            end_time=time.time()
            print('spend %s'%(end_time-start_time))
        return inner
 
  def add():
        for i in range(30000000):
            ret+=i
        print(ret)
 
  add=show_time(add)
  add()

    分析:函數show_time就是裝飾器,它把真正的業務方法func包裹在函數裏面,看起來像add被上下時間函數裝飾了。在這個例子中,函數進入和退出時 ,被稱爲一個橫切面(Aspect),這種編程方式被稱爲面向切面的編程(Aspect-Oriented Programming)。

    @符號是裝飾器的語法糖,在定義函數的時候使用,避免再一次賦值操做,以下示例:

import time
 
  def show_time(func):
      def inner():
          start_time=time.time()
          func()
          end_time=time.time()
          print('spend %s'%(end_time-start_time))
 
      return inner
   
  @show_time      # add=show_time(add)
  def add():
        for i in range(30000000):
            ret+=i
        print(ret) 
 
  @show_time    # bar=show_time(bar)
  def bar():
      print('in the bar')
      time.sleep(2)
 
  add()
  bar()

 如上所示,這樣咱們就能夠省去add = show_time(add)這一句了,直接調用add()便可獲得想要的結果。若是咱們有其餘的相似函數,咱們能夠繼續調用裝飾器來修飾函數,而不用重複修改函數或者增長新的封裝。這樣,咱們就提升了程序的可重複利用性,並增長了程序的可讀性。

    這裏須要注意:add=show_time(add)實際上是把inner引用的對象引用給了add,而inner裏的變量func之因此能夠用,就是由於inner是一個閉包函數。

    @show_time幫咱們作的事情就是當咱們執行業務邏輯foo()時,執行的代碼由粉框部分轉到藍框部分,僅此而已!裝飾器在Python使用如此方便都要歸因於Python的函數能像普通的對象同樣能做爲參數傳遞給其餘函數,能夠被賦值給其餘變量,能夠做爲返回值,能夠被定義在另一個函數內。    

六、帶參數的被裝飾函數

import time
 
  def show_time(func):
      def inner(a,b):
          start_time=time.time()
          func(a,b)
          end_time=time.time()
          print('spend %s'%(end_time-start_time))
 
      return inner
 
  @show_time   # add=show_time(add)
  def add(a,b):
      time.sleep(1)
      print(a+b)
 
  add(2,4)

七、注意點:當被裝飾函數有返回值的狀況

import time

  def show_time(func):
      def inner(a,b):
          start_time=time.time()
          ret=func(a,b)
          end_time=time.time()
          print('spend %s'%(end_time-start_time))
          return ret   # 若被裝飾函數有返回值,則inner函數也必定要返回func(a,b)的結果

      return inner

  @show_time   # add=show_time(add)
  def add(a,b):
      time.sleep(1)
      return a+b

  print(add(2,5))

八、裝飾器在登陸認證方面的應用:

Django爲咱們提供了一個裝飾器函數login_required,當咱們只想限制少許頁面登陸才能訪問時,就可使用裝飾器函數,而沒有必要加中間件。

3、補充

一、使用django的admin頁面錄入數據

  1)首先,在admin.py中配置以下信息:

from django.contrib import admin
  # Register your models here.
  from app01.models import *    # 將models模塊中的全部類(表)引入

  admin.site.register(UserInfo)    # 括號中是model中的類(表),下面也如此
  admin.site.register(Customer)
  admin.site.register(Campuses)
  admin.site.register(ClassList)

  2)建立超級用戶

 python manage.py createsuperuser

  3)以超級用戶登陸admin後臺,開始錄入數據

二、安裝multiselectfield

  方式一:

  pip3 install multiselectfield

  方式二:pycharm軟件上按以下操做

    file -> settints -> Project:xxx -> Project Interpreter -> 右側綠色加號 -> 搜索multiselectfield ->Install Package

  解釋:咱們以前學過gender=models.CharField(choices=(('male','男')('female','女'))),使用modelform會渲染成多個type爲radio的input標籤,model中定義course = MultiSelectField("諮詢課程", choices=(('Linux', 'Linux中高級'),('PythonFullStack', 'Python高級全棧開發'),), blank=True, null=True),使用modelform會渲染成多個type爲checkbox的input標籤。

三、blank=True

  qq_name = models.CharField('QQ暱稱', max_length=64, blank=True, null=True)

  解釋:null=True表示數據庫中不能爲空,blank=True表示使用modelform組件中校驗該字段輸入時不能爲空,而只寫null=True則不能校驗。Django的admin也是基於modelform實現的,因此使用admin提交表單數據時,只寫了null=True而沒有寫blank=True的則必須輸入值,不能爲空。

四、model中模型類的__str__方法必須返回字符串類型,不能返回其餘類型。

五、location的search屬性

  search 屬性是一個可讀可寫的字符串,可設置或返回當前 URL 的查詢部分(即問號 ? 以後的部分)。

六、javascript的slice()方法

  語法:string.slice(start,end)

  解釋:提取字符串的某個部分,並以新的字符串返回被提取的部分,索引從0開始,顧頭不顧尾。

相關文章
相關標籤/搜索