1. 程式人生 > >Django中的ORM(物件關係對映)

Django中的ORM(物件關係對映)

Django與資料庫的命令互動主要是通過manage.py,常用的命令就是manage.py syncdb,可以將model中不在資料庫中存在的表給建立完成,但是隻能建立新的資料表或者列,如果model中將某個已經建立的資料表刪除,syncdb是不會進行同步刪除的操作的。

為什麼要使用ORM:ORM是直接將sql查詢語句封裝為django類,這樣不僅可以方便我們寫程式碼(不用一行一行敲sql命令),提高程式碼的易讀性(從類,類的屬性,屬性的引數就可以知道資料庫裡面有什麼表,表裡面有哪些列,這些列分別又有什麼限制),還可以提高程式碼的安全性(將資料庫具體相關的部分都交給django了,降低了被sql注入的風險)以及可移植性(不論mysql,postgresql程式設計師做的工作都少多了)。


django中的model 有幾個常用的屬性:

1.CharField 和TextField 都是比較常用的屬性;CharFiled 是定長的,而TextField是可以無限長的。
2.除了兩個常用的屬性,還有一些加了驗證的Field,比如說:EmailFiled,URLFiled和IPAdressField;
他們分別可以進行驗證使用者傳入的值是否是有效的Email地址,URL和IP地址。
3.BooleanField和NullBooleanField都是可以儲存True和False的;但是前者不可以是空和NULL,後者可以。
4.FileField和FIlePathField用來儲存使用者上傳的檔案的路徑;
5.Django 會自動為你生成一個名稱為id的主鍵,如果想要自己定義可以通過AutoField屬性;如果希望某個屬性成為主鍵可以在屬性後面加上 primary_key = True;而定義unique=True則可以保證變數值的唯一性;


模型與模型(表與表)之間的關係:
主要有兩種:
1.多對一。
舉例:

class Author(models.Model):
     name = CharField(length=10)

class Book(models.Model):
    title = CharField(max_length=10)
    author = ForeignKey(Author)

這樣的話每一個Book物件都會有一個ForeignKey,也就是author.在業務上的意義就是每一本書都可以對應一個作者,並且不同的書可以對應一個作者,但是這樣有一個缺陷就是,如果一本書有多個作者,這個關係模型就無法表示了。這樣的話就要用到下面的多對多的關係了。

2.多對多。
class Author(models.Model):
      name = CharField(max_length=10)


class Book(models.Model):
     title = CharField(max_length=10)
     author = ManyToManyField(Author)
關係資料庫本身沒多多對多的關係,Django是在資料庫中新建了一張表專門用來儲存多對多的關係。
PS:記得引用的ForeignKey和ManyToManyField一定要在Author的後面,如果不在後面要將引數寫成字串形式('Author')。並且ForeignKey和ManyToManyField這段關係在兩個類裡面都可以宣告,作用是一樣的,django會自動為我們把另外一半關係給對稱過去。

model 類的繼承
共有兩種不同的繼承方式:
1.抽象基礎類
具體表現就是不會建立實際的基類資料表,只會建立子類的資料表;
   class Meta:
       abstract = True
2.多表繼承
具體表現就是每一個類包括父類和子類都會建立一張資料表;
上面講的主要是model中資料庫表的建立,下面開始查詢的部分:
主要使用的是相似的兩個類:Manager和QuerySet


1.除了有特別的指定,Managerl類會預設附著在每一個model類裡面,所以預設情況下每個模型類都會有一個objects屬性,他構成了這個model在資料庫中的所有查詢;

2.幾個常見的查詢方法:
all:返回一個模型中所有資料庫記錄的QuerySet;
filter: 返回一個包含指定條件的模型記錄的QuerySet;
exclude: 和filter 正好相反;
get: 獲取單個符合條件的記錄,(沒找到或者超出一個的記錄都會返回異常;)

(QuerySet即為:資料庫每一行記錄的列表;使用Queryset查詢的資料都是快取在記憶體中的);

books = Books.objects.filter(title_contains="Tree")相當於:
select * from books where title like *%Tree%*

everone = Person.objects.all()相當於:
select * from Person

overdue_books = book_queryset.filter(due_date__lt=today);

QuerySet中有,而Manager物件中沒有的方法:
對查詢的結果排序:
all_sorted_first = Person.objects.all().order_by('first_name');
其他改變查詢的方法:
Person.objects.values('first')返回一個包含所有first name名字的字典;