Django(6)-orm

Django ORM 經常使用字段和參數

經常使用字段

AutoField

int自增列,必須填入參數 primary_key=True。當model中若是沒有自增列,則自動會建立一個列名爲id的列。

IntegerField

一個整數類型,範圍在 -2147483648 to 2147483647。

CharField

字符類型,必須提供max_length參數, max_length表示字符長度。

DateField

日期字段,日期格式  YYYY-MM-DD,至關於Python中的datetime.date()實例。

DateTimeField

 日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],至關於Python中的datetime.datetime()實例。

 

   AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

    BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -3276832767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 032767
    IntegerField(Field)
        - 整數列(有符號的) -21474836482147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 02147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -92233720368547758089223372036854775807

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    EmailField(CharField):
        - 字符串類型,Django Admin以及ModelForm中提供驗證機制

    IPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

    GenericIPAddressField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
        - 參數:
            protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both"

    URLField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證 URL

    SlugField(CharField)
        - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號)

    CommaSeparatedIntegerField(CharField)
        - 字符串類型,格式必須爲逗號分割的數字

    UUIDField(Field)
        - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
        - 參數:
                path,                      文件夾路徑
                match=None,                正則匹配
                recursive=False,           遞歸下面的文件夾
                allow_files=True,          容許文件
                allow_folders=False,       容許文件夾

    FileField(Field)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

    ImageField(FileField)
        - 字符串,路徑保存在數據庫,文件上傳到指定目錄
        - 參數:
            upload_to = ""      上傳文件的保存路徑
            storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
            width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
            height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型
字段合集

自定義字段(瞭解爲主)

class UnsignedIntegerField(models.IntegerField):
    def db_type(self, connection):
        return 'integer UNSIGNED'
================================

class FixedCharField(models.Field):
    """
    自定義的char類型的字段類
    """
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super(FixedCharField, self).__init__(max_length=max_length, *args, **kwargs)

    def db_type(self, connection):
        """
        限定生成數據庫表的字段類型爲char,長度爲max_length指定的值
        """
        return 'char(%s)' % self.max_length


class Class(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=25)
    # 使用自定義的char類型的字段
    cname = FixedCharField(max_length=25)
自定義字段

ORM字段與數據庫實際字段的對應關係

    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
ORM字段與數據庫實際字段的對應關係

字段參數

null

用於表示某個字段能夠爲空。

unique

若是設置爲unique=True 則該字段在此表中必須是惟一的 。

db_index

若是db_index=True 則表明着爲此字段設置索引。

default

爲該字段設置默認值。

 

DateField和DateTimeField

auto_now_add
配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。
auto_now
配置上auto_now=True,每次更新數據記錄的時候會更新該字段。

關係字段

ForeignKey

字段參數

OneToOneField

字段參數

to

設置要關聯的表。

to_field

設置要關聯的字段。

on_delete

同ForeignKey字段。

 

ManyToManyField

字段參數

元信息

db_table

ORM在數據庫中的表名默認是 app_類名,能夠經過db_table能夠重寫表名。

index_together

聯合索引。

unique_together

聯合惟一索引。

ordering

指定默認按什麼字段排序。python

只有設置了該屬性,咱們查詢到的結果才能夠被reverse()。git

 

 

__exact 精確等於 like ‘aaa’
__iexact 精確等於 忽略大小寫 ilike ‘aaa’
__contains 包含 like ‘%aaa%’
__icontains 包含 忽略大小寫 ilike ‘%aaa%’,可是對於sqlite來講,contains的做用效果等同於icontains。
__gt 大於
__gte 大於等於
__lt 小於
__lte 小於等於
__in 存在於一個list範圍內
__startswith 以…開頭
__istartswith 以…開頭 忽略大小寫
__endswith 以…結尾
__iendswith 以…結尾,忽略大小寫
__range 在…範圍內
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False
__isnull=True 與 __exact=None的區別

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()

def __unicode__(self):
return self.name

class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()

def __unicode__(self):
return self.name

class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateTimeField()
authors = models.ManyToManyField(Author)

def __unicode__(self):
return self.headline

這是model,有blog,author,以及entry;其中entry分別與blog與author表關 聯,entry與blog表是經過 外鍵(models.ForeignKey())相連,屬於一對多的關係,即一個entry對應多個blog,entry與author是多對多的關係, 經過modles.ManyToManyField()實現。
1、插入數據庫,用save()方法實現,以下:
>>> from mysite.blog.models import Blog
>>> b = Blog(name=’Beatles Blog’, tagline=’All the latest Beatles news.’)
>>> b.save()

2、更新數據庫,也用save()方法實現,以下:
>> b5.name = ‘New name’
>> b5.save()

保存外鍵和多對多關係的字段,以下例子:
更新外鍵字段和普通的字段同樣,只要指定一個對象的正確類型。
>>> cheese_blog = Blog.objects.get(name=」Cheddar Talk」)
>>> entry.blog = cheese_blog
>>> entry.save()

更新多對多字段時又一點不太同樣,使用add()方法添加相關聯的字段的值。
>> joe = Author.objects.create(name=」Joe」)
>> entry.authors.add(joe)

3、檢索對象

>>> Blog.objects

>>> b = Blog(name=’Foo’, tagline=’Bar’)
>>> b.objects
Traceback:
…
AttributeError: 「Manager isn’t accessible via Blog instances.」

1、檢索全部的對象

>>> all_entries = Entry.objects.all()

使用all()方法返回數據庫中的全部對象。

2、檢索特定的對象
使用如下兩個方法:
fileter(**kwargs)
返回一個與參數匹配的QuerySet,至關於等於(=).
exclude(**kwargs)
返回一個與參數不匹配的QuerySet,至關於不等於(!=)。

Entry.objects.filter(pub_date__year=2006)
不使用Entry.objects.all().filter(pub_date__year=2006),雖然也能運行,all()最好再獲取全部的對象時使用。
上面的例子等同於的sql語句:
slect * from entry where pub_date_year=’2006′

連接過濾器:
>>> Entry.objects.filter(
… headline__startswith=’What’
… ).exclude(
… pub_date__gte=datetime.now()
… ).filter(
… pub_date__gte=datetime(2005, 1, 1)
… )

最後返回的QuerySet是headline like ‘What%’ and put_date2005-01-01

另一種方法:
>> q1 = Entry.objects.filter(headline__startswith=」What」)
>> q2 = q1.exclude(pub_date__gte=datetime.now())
>> q3 = q1.filter(pub_date__gte=datetime.now())
這種方法的好處是能夠對q1進行重用。

QuerySet是延遲加載
只在使用的時候纔會去訪問數據庫,以下:
>>> q = Entry.objects.filter(headline__startswith=」What」)
>>> q = q.filter(pub_date__lte=datetime.now())
>>> q = q.exclude(body_text__icontains=」food」)
>>> print q
在print q時纔會訪問數據庫。

其餘的QuerySet方法
>>> Entry.objects.all()[:5]
這是查找前5個entry表裏的數據

>>> Entry.objects.all()[5:10]
這是查找從第5個到第10個之間的數據。

>>> Entry.objects.all()[:10:2]
這是查詢從第0個開始到第10個,步長爲2的數據。

>>> Entry.objects.order_by(‘headline’)[0]
這是取按headline字段排序後的第一個對象。

>>> Entry.objects.order_by(‘headline’)[0:1].get()
這和上面的等同的。

>>> Entry.objects.filter(pub_date__lte=’2006-01-01′)
等同於SELECT * FROM blog_entry WHERE pub_date <= ’2006-01-01′; >>> Entry.objects.get(headline__exact=」Man bites dog」)
等同於SELECT … WHERE headline = ‘Man bites dog’;

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
這兩種方式是等同的,都是查找id=14的對象。

>>> Blog.objects.get(name__iexact=」beatles blog」)
查找name=」beatles blog」的對象,不去飯大小寫。

Entry.objects.get(headline__contains=’Lennon’)
等同於SELECT … WHERE headline LIKE ‘%Lennon%’;

startswith 等同於sql語句中的 name like ‘Lennon%’,
endswith等同於sql語句中的 name like ‘%Lennon’.

>>> Entry.objects.filter(blog__name__exact=’Beatles Blog’)
查找entry表中外鍵關係blog_name=’Beatles Blog’的Entry對象。

>>> Blog.objects.filter(entry__headline__contains=’Lennon’)
查找blog表中外鍵關係entry表中的headline字段中包含Lennon的blog數據。

Blog.objects.filter(entry__author__name=’Lennon’)
查找blog表中外鍵關係entry表中的author字段中包含Lennon的blog數據。

Blog.objects.filter(entry__author__name__isnull=True)
Blog.objects.filter(entry__author__isnull=False,entry__author__name__isnull=True)
查詢的是author_name爲null的值

Blog.objects.filter(entry__headline__contains=’Lennon’,entry__pub_date__year=2008)
Blog.objects.filter(entry__headline__contains=’Lennon’).filter( entry__pub_date__year=2008)
這兩種查詢在某些狀況下是相同的,某些狀況下是不一樣的。第一種是限制全部的blog數據的,而第二種狀況則是第一個filter是
限制blog的,而第二個filter則是限制entry的

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact
等同於select * from where id=14

# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])
等同於select * from where id in{1,4,7}
# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)
等同於select * from id>14

>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3) # __exact is implied
>>> Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
這三種狀況是相同的

>>> Entry.objects.filter(headline__contains=’%')
等同於SELECT … WHERE headline LIKE ‘%\%%’;

Caching and QuerySets

>>> print [e.headline for e in Entry.objects.all()]
>>> print [e.pub_date for e in Entry.objects.all()]
應改寫爲:
>> queryset = Poll.objects.all()
>>> print [p.headline for p in queryset] # Evaluate the query set.
>>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.、
這樣利用緩存,減小訪問數據庫的次數。

4、用Q對象實現複雜的查詢

Q(question__startswith=’Who’) | Q(question__startswith=’What’)
等同於WHERE question LIKE ‘Who%’ OR question LIKE ‘What%’

Poll.objects.get(
Q(question__startswith=’Who’),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
等同於SELECT * from polls WHERE question LIKE ‘Who%’ AND (pub_date = ’2005-05-02′ OR pub_date = ’2005-05-06′)

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)))

5、比較對象

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

6、刪除

Entry.objects.filter(pub_date__year=2005).delete()

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

Entry.objects.all().delete()
刪除全部

7、一次更新多個值

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline=’Everything is the same’)

>>> b = Blog.objects.get(pk=1)
# Change every Entry so that it belongs to this Blog.
>>> Entry.objects.all().update(blog=b)

若是用save()方法,必須一個一個進行保存,須要對其就行遍歷,以下:
for item in my_queryset:
item.save()

關聯對象

one-to-many
>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # 「UPDATE blog_entry SET blog_id = NULL …;」

>>> e = Entry.objects.get(id=2)
>>> print e.blog # Hits the database to retrieve the associated Blog.
>>> print e.blog # Doesn’t hit the database; uses cached version.

>>> e = Entry.objects.select_related().get(id=2)
>>> print e.blog # Doesn’t hit the database; uses cached version.
>>> print e.blog # Doesn’t hit the database; uses cached version

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains=’Lennon’)
>>> b.entry_set.count()

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Returns all Entry objects related to Blog.
# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains=’Lennon’)
>>> b.entries.count()

You cannot access a reverse ForeignKey Manager from the class; it must be accessed from an instance:
>>> Blog.entry_set

add(obj1, obj2, …)
Adds the specified model objects to the related object set.
create(**kwargs)
Creates a new object, saves it and puts it in the related object set. Returns the newly created object.
remove(obj1, obj2, …)
Removes the specified model objects from the related object set.
clear()
Removes all objects from the related object set.

many-to-many類型:
e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains=’John’)
a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

one-to-one 類型:
class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object

使用sql語句進行查詢:

def my_custom_sql(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute(「SELECT foo FROM bar WHERE baz = %s」, [self.baz])
row = cursor.fetchone()
return row
python django 數據庫查詢方法總結

 

這裏必須添加,models才能被記錄sql

 

課後習題

表示7天的時間間隔,用於表示優惠券的過時時間
爲何要定義一個char字段,char字段的做用是什麼
查book的全部對象
title是圍城
id=1
id大於2
id小於2
id大於等於2
出版日期是2017年的書
出版日期大於2017年的書
書名包含圍字的
包含圍字且出版年份是2018年的
get方法與filter方法的區別
取2018年出版的書的書名和出版日期
取2018年出版的書的書名和出版日期,且返回列表形式
 
CBV 中的META的table_name怎麼取出來
<9> distinct():            
從返回結果中剔除重複紀錄(若是你查詢跨越多個表,可能在計算QuerySet時獲得重複的結果。此時可使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
  - models.CASCADE,刪除關聯數據,與之關聯也刪除
   DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

DateField和DateTimeField

auto_now_add

配置auto_now_add=True,建立數據記錄的時候會把當前時間添加到數據庫。數據庫

db_constraint

是否在數據庫中建立外鍵約束,默認爲True。django

db_index

若是db_index=True 則表明着爲此字段設置索引。緩存

#一對多或稱爲多對一
三張表:出版社,做者信息,書

一對多(或多對一):一個出版社能夠出版多本書

關聯方式:foreign key
#多對多
三張表:出版社,做者信息,書

多對多:一個做者能夠寫多本書,一本書也能夠有多個做者,雙向的一對多,即多對多
  
關聯方式:foreign key+一張新的表
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息