久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Django筆記教程:三,、Model進階

 zhou網(wǎng)摘 2018-03-02

Model 進階學習

簡介

Django經(jīng)常被用于一些創(chuàng)業(yè)團隊,,乃是因為其非常適合敏捷開發(fā),,開發(fā)效率非常之高。Model 作為Django重要組成部分也是亮點之一,,著實需要我們花時間好好梳理一遍,。
ORM需要好好學習一下,運用得當可以大大的提升代碼的簡潔性,。Django的model模塊,,遵循了DRY(don’t repeat yourself)原則,也會使得代碼更加容易維護,,只需修改一次,,肯定會大大提高程序的健壯性以及可維護性。
而且ORM也使得該框架更加靈活且松解耦,。例如有些碼農(nóng)不喜歡django的模版,,更偏愛其他的模版渲染引擎。django視圖方法并未強制一定要使用自身的模版引擎,,你一可以嘗試實用jinjia2等等,。同時ORM屏蔽了底層數(shù)據(jù)庫的語法,你可以運行非常多的數(shù)據(jù)庫類型(mysql,mongo?don’t care,,改一下engine配置即可),,當然性能肯定會降低一些,畢竟多封裝了一層,。

一路走來,踩過無數(shù)的大坑,,發(fā)現(xiàn)網(wǎng)上很多網(wǎng)友的博文是誤導性的,,所以想在這里寫一片文章梳理一下model的全貌,以備復習,,也供給大家一個參考,,如果發(fā)現(xiàn)錯誤希望可以幫忙指正,謝謝,。

本文結構:

  1. model常用字段定義
  2. model的初級用法
  3. model的高級用法
  4. model的一些坑

1.model常用字段定義

    V=models.CharField(max_length=None[, **options])    #varchar
    V=models.EmailField([max_length=75, **options])    #varchar
    V=models.URLField([verify_exists=True, max_length=200, **options])    #varchar
    V=models.FileField(upload_to=None[, max_length=100, **options])    #varchar
    #upload_to指定保存目錄可帶格式,,
    V=models.ImageField(upload_to=None[, height_field=None, width_field=None, max_length=100, **options])
    V=models.IPAddressField([**options])    #varchar
    V=models.FilePathField(path=None[, match=None, recursive=False, max_length=100, **options]) #varchar
    V=models.SlugField([max_length=50, **options])    #varchar,標簽,,內(nèi)含索引
    V=models.CommaSeparatedIntegerField(max_length=None[, **options])    #varchar
    V=models.IntegerField([**options])    #int
    V=models.PositiveIntegerField([**options])    #int 正整數(shù)
    V=models.SmallIntegerField([**options])    #smallint
    V=models.PositiveSmallIntegerField([**options])    #smallint 正整數(shù)
    V=models.AutoField(**options)    #int,;在Django代碼內(nèi)是自增
    V=models.DecimalField(max_digits=None, decimal_places=None[, **options])    #decimal
    V=models.FloatField([**options])    #real
    V=models.BooleanField(**options)    #boolean或bit
    V=models.NullBooleanField([**options])    #bit字段上可以設置上null值
    V=models.DateField([auto_now=False, auto_now_add=False, **options])    #date
    #auto_now最后修改記錄的日期;auto_now_add添加記錄的日期
    V=models.DateTimeField([auto_now=False, auto_now_add=False, **options])    #datetime
    V=models.TimeField([auto_now=False, auto_now_add=False, **options])    #time
    V=models.TextField([**options])    #text
    V=models.XMLField(schema_path=None[, **options])    #text
    ——————————————————————————–
    V=models.ForeignKey(othermodel[, **options])    #外鍵,,關聯(lián)其它模型,,創(chuàng)建關聯(lián)索引
    V=models.ManyToManyField(othermodel[, **options])    #多對多,關聯(lián)其它模型,,創(chuàng)建關聯(lián)表
    V=models.OneToOneField(othermodel[, parent_link=False, **options])    #一對一,,字段關聯(lián)表屬性
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

2.model初級用法

首先我們拿官網(wǎng)的例子作為示范,這個例子非常的經(jīng)典,,被用在django book以及其他很多相關的書籍當中,。
我們首先假定如下的概念:

  • 一個作者有姓,名,,email地址,。
  • 出版商有名稱,地址,,所在的city,province,country,website.
  • 書籍有書名和出版日期,。它有一個或者多個作者[many-2-many]。但是只有一個出版商([one 2 many]),,被稱為外鍵[foreign key],。

在models.py中添加如下內(nèi)容:

from django.db import models
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    def __unicode__(self):
        return self.name

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    def __unicode__(self):
        return self.title
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

并且記得在配置里面加入app model注冊,
也需要在setting.py中加入books的app
之后可以用python manage.py validate 校驗模型的正確性。
也可以用python mange.py sqlall books 來查看sql生成的語句,。
相應的生成圖片
后面還需要執(zhí)行
python manage.py syncdb

基本的添加數(shù)據(jù)

這里寫圖片描述

基本的選擇對象

選擇所有的對象

  • 獲取全體對象:
    Publisher.objects.all()可以用來獲取所有的對象.
  • 篩選部分對象:
    Publisher.objects.filter(name='Apress')可以用來篩選所有name是Apress的publisher.(獲取的是一個對象列表)
  • 獲取單個對象
    Publisher.objects.get(name='Apress')
    獲取一個名字是Apress的開發(fā)商(只獲取單個對象),。 filter的條件會在高級部分列出。
  • 排序:
    publisher.objects.order_by("state_province","-address").這句代碼幾乎囊括了排序的精華:).我們可以看到是多字段排序,,同時,,address前面有一個-代表的是逆排序。
    當然,,一般情況下,,只需要按照某個字段進行排序,這種情況下可以指定模型的缺省排序方式:
    meta
  • 連查:
    除了單個查詢,,我們還可以用下面這種方式來查詢
    Publisher.objects.filter(name='xxoo').order_by('-name')[0]
    這段程序并不會執(zhí)行兩次,,而是最后轉(zhuǎn)化為一句sql語句來執(zhí)行(考慮的太周到).
  • 更新多個對象:
    我們知道,,之前我們用p.save()來更新對象,如果涉及到很多條數(shù)據(jù)需要一次性更新,,這個時候該如何呢,?Django也考慮到了這一點,可以用如下的方式來更新:
    Publisher.objects.all().update(country='China'),,一次性將所有的Publisher的國家更新為china,。
  • 刪除對象:
    前面講了添加、更新,,這里補充一下刪除,,刪除主要是篩選出對象后執(zhí)行delete()方法.
    Publisher.objects.filter(country='USA').delete()

3.model的高級用法

訪問外鍵

>>>b=Book.objects.get(id=1)
>>>b=p.publisher
<publisher:Apress Publishing>
>>>b.publisher.website
u'http://www.'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

對于Foreignkey 來說,關系的另外一端,,也可以追溯回來,,不過由于不是對稱關系,所以有一些區(qū)別,,獲得的是一個list,,而非單一對象:

>>>p=Publisher.objects.get(name="Apress Publishing")
>>>p.book_set.all()
[<Book:The Chinese english>,<Book:the good good study>,...]
  • 1
  • 2
  • 3

訪問多對多值

多對多和外鍵工作方式類似,不過我們處理的是QuerySet而非模型實例,。例如,,查看書籍的作者:

>>>b = Book.objects.get(id=1)
>>>b.authors.all()
[<Author:liushuchun>,<Author:nobb>]
>>>b.authors.filter(fisrt_name="liushuchun")
[<Author:liushuchun>]
  • 1
  • 2
  • 3
  • 4
  • 5

我們可以看到這就是類似objects來用了。

更改數(shù)據(jù)庫結構

Django有一個不完善的地方是,,一旦model確定下來后,再想通過命令來更新是無法更新的,,會報錯,,這個時候就要學會用手動的方式更改數(shù)據(jù)庫結構。
具體的過程:
1. 先在models.py文件中,,找到你要添加字段的模型,,添加(也可以是刪除修改,只是sql語句有一些區(qū)別)上該字段,,如下所示(抱歉,,截圖多了個等號)
添加字段
2. 在cmd下,通過cd命令進入應用目錄,,也就是manage.py文件所在的目錄
3. 然后使用python manage.py sqlall[app_name]命令,,打印出app中包括的所有模型的sql語言表示
這里寫圖片描述
3. 找到你想要添加字段的表,找到你已經(jīng)添加過的字段test,,記下sql語句
4. 進入 manage.py shell 創(chuàng)建一個cursor實例,,用于執(zhí)行sql語句
這里寫圖片描述
5. 執(zhí)行該sql語句,看好了,,這個sql語句是剛才我讓你記下的sql語句,,執(zhí)行這個命令就可以完成向數(shù)據(jù)庫添加字段.
這里寫圖片描述
6. 最后,,我們要驗證添加字段是否成功,仍然在manage.py shell中,,通過調(diào)用模型來檢查是否成功,。
這里我們只說了添加字段,其他刪除或者修改字段類似,。

manager管理器添加自定義方法

管理器是Django查詢數(shù)據(jù)庫時會使用到的一個特別的對象,,在Book.objects.all()語法中,objects就是管理器,,在django中,,每一個model至少有一個管理器,而且,,你也可以創(chuàng)建自己的管理器來自定義你的數(shù)據(jù)庫訪問操作,。一方面可以增加額外的管理器方法,另一方面可以根據(jù)你的需求來修改管理器返回的QuerySet,。
這是一種”表級別”的操作,,下面我們給之前的Book類增加一個方法title_count(),它根據(jù)關鍵字,,
返回標題中包括這個關鍵字的書的個數(shù),。

class BookManager(models.Manager):
    def title_count(self, keyword):
        return self.filter(title__icontains=keyword).count()
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管理器,也可以定義一個新的管理器變量
    #調(diào)用時,,直接使用這個新變量就可以了,,一旦定義了新的管理器,默認管理器
    #需要顯示聲明出來才可以使用
    # objects = models.Manger()
    objects = BookManager()

    def __unicode__(self):
        return self.title
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

結果為:

>>>Book.objects.title_count('python')
2
  • 1
  • 2

上面的代碼可以看到,,創(chuàng)建自定義的Manager的步驟:
1. 繼承models.Manager,,定義新的管理器方法,在方法中使用self,,也就是manager本身來
進行操作
2. 把自定義的管理器對象賦值給objects屬性來代替默認的管理器,。
那為什么不直接創(chuàng)建個title_count函數(shù)來實現(xiàn)這個功能呢?
因為創(chuàng)建管理器類,,可以更好地進行封裝功能和重用代碼,。

修改返回的QuerySet

Book.objects.all()返回的是所有記錄對象,可以重寫Manager.get_query_set()方法,,它返回的是你自定義的QuerySet,,你之后的filter,slice等操作都是基于這個自定義的QuerySet。

from django.db import models

class RogerBookManager(models.Manager):
    def get_query_set(self):
        #調(diào)用父類的方法,,在原來返回的QuerySet的基礎上返回新的QuerySet
        return super(RogerBookManager, self).get_query_set().filter(title__icontains='python')

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)

    #objects默認管理器需要顯示聲明,,才能使用
    objects = models.Manager() # 默認的管理器
    roger_objects = RogerBookManager() # 自定義的管理器,用新變量
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

結果為:

>>>Book.objects.all()
[<Book:Coplier Theroy>,<Book:python>,...]
>>>Book.roger_objects.all()
[<Book:Python Tutorial>,<Book:Python tools>]
  • 1
  • 2
  • 3
  • 4

你可以為model定義多個不同的管理器來返回不同的QuerySet,不過要注意一點的是Django
會把你第一個定義的管理器當作是默認的管理器,,也就是代碼行中最上面定義的管理器,。Django
有些其它的功能會使用到默認的管理器,為了能讓它正常的工作,,一種比較好的做法就是把原始默認
的管理器放在第一個定義,。

Model添加方法(這部分是抄書)

和管理器的”表級別”操作相比,model的方法更像是”記錄級別”的操作,,不過,,model的主要設計是用來
用”表級別”操作的,”記錄級別”的操作往往是用來表示記錄的狀態(tài)的,,是那些沒有放在數(shù)據(jù)庫表中,,但是也
有意義的數(shù)據(jù)。舉例說明:

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)

    # 用來判讀是否在baby boomer出生,,可以不用放在數(shù)據(jù)庫表中
    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
            return "Baby boomer"
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        return "Post-boomer"

    # 用來返回全名,,這個可以不被插入到數(shù)據(jù)庫表中
    def get_full_name(self):
        "Returns the person's full name."
        return u'%s %s' % (self.first_name, self.last_name)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

運行結果:

>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.get_full_name()
u'Barack Obama'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

執(zhí)行自定義SQL語句

如果你想執(zhí)行自定義的SQL語句查詢,可以使用django.db.connection對象:
可以使用SQL對數(shù)據(jù)庫中所有的表進行操作,,而不用引用特定的model類,。
需要注意的是execute()函數(shù)使用的SQL語句需要使用到%s這樣的格式符,而
不是直接寫在里面,。
這樣的操作比較自由,,比較好的做法是把它放在自定義管理器中:

from django.db import connection, models

class PythonBookManager(models.Manager):
    def books_titles_after_publication(self, date_string):
        cursor = connection.cursor()
        cursor.execute("""
            SELECT title
            FROM books_book
            WHERE publication_date > %s""", [date_string])
        #fetchall()返回的是元組的列表
        return [row[0] for row in cursor.fetchall()]

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField(blank=True, null=True)
    num_pages = models.IntegerField(blank=True, null=True)

    objects = models.Manager()
    python_objects = PythonBookManager()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

一些django奇技淫巧

還在搜集中,后面會加上.
  • 1
  • 2

一些過濾字段方法

1.多表連接查詢:當我知道這點的時候頓時覺得django太NX了,。

  class A(models.Model):
    name = models.CharField(u'名稱')
  class B(models.Model):
    aa = models.ForeignKey(A)
B.objects.filter(aa__name__contains='searchtitle')
  • 1
  • 2
  • 3
  • 4
  • 5

1.5 我叫它反向查詢,,后來插入記錄1.5,當我知道的時候瞬間就覺得django太太太NX了,。

class A(models.Model):
name = models.CharField(u'名稱')
class B(models.Model):
aa = models.ForeignKey(A,related_name="FAN")
bb = models.CharField(u'名稱')

查A: A.objects.filter(FAN=’XXXX’),,都知道related_name的作用,A.FAN.all()是一組以A為外鍵的B實例,,可前面這樣的用法是查詢出所有(B.aa=A且B.bb=XXXX)的A實例,然后還可以通過__各種關系查找,,真赤激?。?!

**2.條件選取querySet的時候,,filter表示=,exclude表示!=querySet.distinct() 去重復

__exact 精確等于 like 'aaa'
 __iexact 精確等于 忽略大小寫 ilike 'aaa'
 __contains 包含 like '%aaa%'
 __icontains 包含 忽略大小寫 ilike '%aaa%',,但是對于sqlite來說,,contains的作用效果等同于icontains。
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in 存在于一個list范圍內(nèi)
__startswith 以...開頭
__istartswith 以...開頭 忽略大小寫
__endswith 以...結尾
__iendswith 以...結尾,,忽略大小寫
__range 在...范圍內(nèi)
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
>> q1 = Entry.objects.filter(headline__startswith="What")
>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>> q3 = q1.filter(pub_date__gte=datetime.date.today())
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
  • 1
  • 2
  • 3
  • 4
  • 5

即q1.filter(pub_date__gte=datetime.date.today())表示為時間>=now,,q1.exclude(pub_date__gte=datetime.date.today())表示為<=now

關于緩存:
queryset是有緩存的,,a = A.objects.all(),print [i for i in a].第一次執(zhí)行打印會查詢數(shù)據(jù)庫,然后結果會被保存在queryset內(nèi)置的cache中,,再執(zhí)行print的時候就會取自緩存,。

DJANGO or 查詢

Q查詢——對對象的復雜查詢
F查詢——專門取對象中某列值的操作

Q查詢
1、Q對象(django.db.models.Q)可以對關鍵字參數(shù)進行封裝,,從而更好地應用多個查詢,,例如:

from django.db.models import Q
from login.models import New #models對象

news=New.objects.filter(Q(question__startswith='What'))
  • 1
  • 2
  • 3
  • 4

2、可以組合使用&,|操作符,,當一個操作符是用于兩個Q的對象,它產(chǎn)生一個新的Q對象,。

Q(question__startswith='Who') | Q(question__startswith='What')
  • 1

3、Q對象可以用~操作符放在前面表示否定,,也可允許否定與不否定形式的組合

Q(question__startswith='Who') | ~Q(pub_date__year=2005)
  • 1

4,、應用范圍

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
  • 1
  • 2
  • 3
  • 4

等價于

SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
  • 1
  • 2

5、Q對象可以與關鍵字參數(shù)查詢一起使用,,不過一定要把Q對象放在關鍵字參數(shù)查詢的前面,。

正確:
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')

錯誤:
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Done!有一些粗略,但是大概能用的上的,,幾乎都在這里了,。

參考

the dango book2.0 http://www./en/2.0/

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多