django模型一

http://www.cnblogs.com/cheungjustin/archive/2011/12/10/2283559.html

歡迎各位python django愛好者加入我們的PDW大家庭!QQ羣:80692368

MTV開發模式

M 代表模型(Model),即數據存取層。 該層處理與數據相關的所有事務: 如何存取、如何驗證有效性、包含哪些行爲以及數據之間的關係等。

T 代表模板(Template),即表現層。 該層處理與表現相關的決定: 如何在頁面或其他類型文檔中進行顯示。

V 代表視圖(View),即業務邏輯層。 該層包含存取模型及調取恰當模板的相關邏輯。 你可以把它看作模型與模板之間的橋樑。

Django MVC 中:視圖用來描述要展現給用戶的數據;不是數據 如何展現 ,而且展現 哪些 數據。 ?

Ruby on Rails 及一些同類框架:控制器負責決定向用戶展現哪些數據,而視圖則僅決定 如何 展現數據,而不是展現 哪些 數據。 ?

數據庫配置

settings.py

DATABASE_ENGINE = '' #數據庫引擎
DATABASE_NAME = ''    #數據庫名稱
DATABASE_USER = ''    #用哪個用戶連接數據庫
DATABASE_PASSWORD = '' #連接用戶的密碼
DATABASE_HOST = ''     #數據庫服務器
DATABASE_PORT = ''    #數據庫服務器端口

測試

>>> from django.db import connection

>>> cursor = connection.cursor()

Django項目(project)和應用(app)

一個project包含很多個Django app以及對它們的配置。

技術上,project的作用是提供配置文件,比方說哪裏定義數據庫連接信息, 安裝的app列表,TEMPLATE_DIRS ,等等

一個app是一套Django功能的集合,通常包括模型和視圖,按Python的包結構的方式存在。

例如,Django本身內建有一些app,例如註釋系統和自動管理界面。 app的一個關鍵點是它們是很容易移植到其他project和被多個project複用。當然,一個project也可以不用創建app,但是如果你使用了Django的數據庫層(模型),你 必須創建一個Django app

創建app

python manage.py startapp books
創建模型
Django模型是用Python代碼形式表述的數據在數據庫中的定義。
對數據層來說它等同於 CREATE TABLE 語句,只不過執行的是Python代碼而不是 SQL,
而且還包含了比數據庫字段定義更多的含義(如URL)。

#Django提供了實用工具來從現有的數據庫表中自動掃描生成模型。

#“每個數據庫表對應一個類”這條規則的例外情況是多對多關係

from django.db import models
class Author(models.Model): #創建模型的示例
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)

        email = models.EmailField('e-mail',blank=True, null=True)

                      #blank=True,null=True設置字段是可選,可null的,'e-mail‘|verbose_name='e-mail' 自定義標籤爲e-mail

        def __unicode__(sefl): #此方法告訴Python如何將對象以unicode的方式顯示出來,'e-mail'是

                 return self.first_name

        class Meta:                 #缺省人排序方式
                 ordering = ['first_name']

#會自動爲模型生成一個自增長的整數主鍵字段,每個Django模型都要求有單獨的主鍵:id

#請確保你的每一個模型裏都包含 __unicode__() 方法

模型安裝
激活 模型
settings.pyINSTALLED_APPS 設置 告訴 Django 項目哪些 app 處於激活狀態。
            MIDDLEWARE_CLASSES  設置
驗檢 模型
python manage.py validate
創建數據表

生成 CREATETABLE 語句

python manage.py sqlall books

生成數據表

python manage.py sqlall books 打印出books app的數據表的sql語句#主要是用來檢查

python manage.py syncdb 生成表

syncdb 命令是同步模型到數據庫的一個簡單方法。 它根據 INSTALLED_APPS 的設置檢查數據庫,如表不存在,就會創建它。 注意:syncdb 並 不能將模型的修改或刪除同步到數據庫。重複運行pythonmanage.pysyncdb總是安全的,因爲它不會重複執行SQL語句

基本數據訪問

from books.models import Publisher   #導入Publisher模型類

1.增加

>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue') #創建類實例,設置字段值
>>> p1.save()   #將對象保存到數據庫中。 Django 會在後臺執行一條 INSERT 語句

>>> Publisher.objects.create(name='Apress', address='2855 Telegraph Avenue')#一步完成對象的創建與存儲,等同上兩句

2查詢

>>> publisher_list = Publisher.objects.all() #從數據庫取出出版商的信息,後臺執行一條 select 語句,返回QuerySet 對象

返回一個記錄集(QuerySet)

Publisher.objects.filter(country="U.S.A.", state_province="CA",name__contains="press")

查找類型有:contains(like),icontains(大小寫無關的LIKE),startswith和endswith, 還有range(BETWEEN查詢)

返回單個對象

Publisher.objects.get(name="Apress") #如果結果是多個對象,會導致拋出異常DoesNotExist

捕獲並處理DoesNotExist異常

try:
   p = Publisher.objects.get(name='Apress')
except Publisher.DoesNotExist:
   print "Apress isn't in the database yet."
else:
   print "Apress is in the database."

數據排序

>>> Publisher.objects.order_by("state_province", "address","-name") [0] #減號是反向排序 [0]是取第一個也可用[0:2]不可用負

3. 更新

>>>Publisher.objects.all().update(country='USA') #修改所有記錄某字段

>>>Publisher.objects.filter(id=52).update(name='Apress Publishing')#修改指定記錄指定字段

4.刪除
>>> p = Publisher.objects.get(name="O'Reilly")  
>>> p.delete()                                       #刪除指定記錄
>>> Publisher.objects.filter(country='USA').delete() #刪除記錄集
>>> Publisher.objects.all().delete()                 #刪除所有記錄

訪問外鍵(Foreign Key)值

當你獲取一個ForeignKey 字段時,你會得到相關的數據模型對象。 例如:

>>> b = Book.objects.get(id=50)
>>> b.publisher
<Publisher: Apress Publishing>
>>> b.publisher.website
u'http://www.apress.com/'

對於用`` ForeignKey`` 來定義的關係來說,在關係的另一端也能反向的追溯回來,只不過由於不對稱性的關係而稍有不同。 通過一個`` publisher`` 對象,直接獲取 books ,用 publisher.book_set.all() ,如下:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.all()
[<Book: The Django Book>, <Book: Dive Into Python>, ...]

實際上,book_set 只是一個 QuerySet(參考第5章的介紹),所以它可以像QuerySet一樣,能實現數據過濾和分切,例如:

>>> p = Publisher.objects.get(name='Apress Publishing')
>>> p.book_set.filter(name__icontains='django')
[<Book: The Django Book>, <Book: Pro Django>]

屬性名稱book_set是由模型名稱的小寫(如book)加_set組成的。

訪問多對多值(Many-to-Many Values)

>>> b = Book.objects.get(id=50)
>>> b.authors.all()
>>> b.authors.filter(first_name='Adrian')
#反向查詢也可以

更改數據庫模式

Django的數據庫層的工作流程

*如果模型包含一個未曾在數據庫裏建立的字段,Django會報出錯信息。 當你第一次用Django的數據庫API請求表中不存在的字段時會導致錯誤(就是說,它會在運行時出錯,而不是編譯時)。

*Django關心數據庫表中是否存在未在模型中定義的列。

*Django關心數據庫中是否存在未被模型表示的表格。

*改變模型的模式架構意味着需要按照順序更改Python代碼和數據庫。

1添加字段

添加 非NULL 字段

首先,進入開發環境(也就是說,不是在發佈環境裏):

     在你的模型裏添加字段。

     運行 manage.pysqlall[yourapp] 來測試模型新的 CREATETABLE 語句。 注意爲新字段的列定義。

     開啓數據庫交互命令界面(比如psql或mysql ,或者可以使用 manage.pydbshell ),執行 ALTERTABLE 語句來添加新列。

     使用Python的manage.pyshell,通過導入模型和選中表單來驗證字段是否正確添加 ,如一切順利,所有語句都不會報錯。

然後在你的產品服務器上再實施一遍這些步驟:

     啓動數據庫的交互界面

     執行在開發環境步驟中,第三步的ALTERTABLE語句。

     將新的字段加入到模型中,如果你使用了某種版本控制工具,並且在第一步中,已經提交了你在開發環境上的修改,現在,可以在生產環境中更新你的代碼了(例如,如果你使用Subversion,執行svnupdate)

      重新啓動Web server,使修改生效。

2刪除字段

  從Model中刪除字段,然後重新啓動你的web服務器,用以下命令從數據庫中刪除字段

  ALTER TABLE books_book DROP COLUMN num_pages;

3刪除多對多關聯字段

  從你的模型中刪除ManyToManyField,然後重啓web服務器,用下面的命令從數據庫刪除關聯表:

  DROP TABLE books_book_authors;

4刪除模型

  從文件中刪除你想要刪除的模型,然後重啓web 服務器models.py,然後用以下命令從數據庫中刪除表:

  DROP TABLE books_book;

Managers

在語句Book.objects.all()中,objects是一個特殊的屬性,需要通過它查詢數據庫。 在第5章,我們只是簡要地說這是模塊的manager 。現在是時候深入瞭解managers是什麼和如何使用了。

總之,模塊manager是一個對象,Django模塊通過它進行數據庫查詢。 每個Django模塊至少有一個manager,你可以創建自定義manager以定製數據庫訪問。

下面是你創建自定義manager的兩個原因: 增加額外的manager方法,修改manager返回的初始QuerySet。

爲模型增加額外的Manager方法

class BookManager(models.Manager):
  def title_count(self,keyword):
     return self.filter(title__icontains=keyword).count() #此處self指manager本身
class Book(models.Model):
  title=models.CharField(max_length=100)
  authors=models.ManyToManyField(Author)
  publisher=models.ForeignKey(Publisher)
  publication_date=models.DateField()
  num_pages=models.IntegerField(blank=True,null=True)
  objects=BookManager()   #也可objects_test, Book.objects_test.title_count('python')

#將取代模型的默認manager(objects)如沒定義,會自動創建,命名爲objects,爲了與自動創建的manager保持一致
  def __unicode__(self):
    return self.title

調用:
>>> Book.objects.title_count('python')
18

修改manager返回的初始QuerySet

class MaleManager(models.Manager):
    def get_query_set(self):
        return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
    def get_query_set(self):
        return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
    people = models.Manager()  #將objects設置成manager的實例,如不這麼做,可用的manager只是men,women
    men = MaleManager()
    women = FemaleManager()
這個例子允許你執行`` Person.men.all()`` ,`` Person.women.all()`` ,`` Person.people.all()`` 查詢,

注意:Django將會把第一個Manager 定義爲默認Manager,你應該小心地選擇你的默認manager。因爲覆蓋get_query_set()

了,你可能接受到一個無用的返回對像

模型方法

from django.contrib.localflavor.us.models import USStateField
from django.db import models
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    birth_date = models.DateField()
    address = models.CharField(max_length=100)
    city = models.CharField(max_length=50)
    state = USStateField() # Yes, this is U.S.-centric...
    def is_midwestern(self):
        "Returns True if this person is from the Midwest."
        return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
    def _get_full_name(self):
        "Returns the person's full name."
        return u'%s %s' % (self.first_name, self.last_name)
    full_name = property(_get_full_name) #property ?!

#調用

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.is_midwestern()
>>> p.full_name

執行原始SQL查詢

有時候你發現Django數據庫API帶給你的也只有這麼多,那你可以寫一些自定義SQL查詢。 你可以通過導入django.db.connection對像來實現,它代表當前數據庫連接。 要使用它,需要通過connection.cursor()得到一個遊標對像。 然後,使用cursor.execute(sql,[params])來執行SQL語句,使用cursor.fetchone()或者cursor.fetchall()來返回記錄集。 例如:

from django.db import connection, models
class PersonManager(models.Manager):
    def first_names(self, last_name):
        cursor = connection.cursor()
        cursor.execute("""
            SELECT DISTINCT first_name
            FROM people_person
            WHERE last_name = %s""", [last_name])
        return [row[0] for row in cursor.fetchone()]
class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    objects = PersonManager()

#不要把視圖代碼和django.db.connection語句混雜,把它們放在自定義模型或自定義manager方法中是個不錯的主意。

#使用方法

>>> Person.objects.first_names('Lennon')
['John', 'Cynthia']

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章