Django 【orm】總結 django orm總結
django orm總結
目錄
1.1.1 生成查詢
1.1.2 建立物件
1.1.3 儲存修改的物件
1.1.4 儲存 ForeignKey 和 ManyToManyField 欄位
1.1.5 檢索物件
1.1.6 檢索所有的物件
1.1.7 過濾檢索特定物件
1.1.8 連結過濾
1.1.9 過濾結果集是唯一
1.2.1 結果集是延遲的
1.2.2 其他的QuerySet方法
1.2.3 限制 QuerySets
1.2.4 欄位查詢
1.2.5 跨關係查詢
1.2.6 過濾器可參考模型欄位
1.2.7 快取查詢集
1.2.8 比較物件
1.2.9 刪除物件
1.3.1 一次修改多個物件
1.3.2 關係物件
1.3.3 One-to-many關係
1.3.4 Many-to-many關係
1.3.5 One-to-one關係
1.1.1 生成查詢
你建立完資料模型,django會自動提供給你資料庫抽象的API,可以建立、獲取、修改、刪除物件,本篇文件講解如何使用API。
我們參考下面模型,一個weblog:
#部落格 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) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __unicode__(self): return self.headline
1.1.2 建立物件
用python物件描述資料庫表的資料,django使用一個直觀的系統,一個模型類描述一個數據表,一個類的例項描述表的一條詳細記錄。使用模型的save()方法將物件建立到資料庫。
from mysite.blog.models import Blog b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') b.save()
只有執行save方法時,django才會執行sql把物件寫入資料庫。
1.1.3 儲存修改的物件
儲存修改仍然使用save()方法
b5.name = 'New name' b5.save()
1.1.4 儲存 ForeignKey 和 ManyToManyField 欄位
cheese_blog = Blog.objects.get(name="Cheddar Talk") entry.blog = cheese_blog #為 ManyToManyField 增加記錄 entry.save()
joe = Author.objects.create(name="Joe") entry.authors.add(joe) #為 ForeignKey 增加記錄
1.1.5 檢索物件
從資料庫裡檢索物件,可以通過模型的Manage來建立QuerySet,一個QuerySet表現為一個數據庫中物件的結合,他可以有0個一個或多個過濾條件,在SQL裡QuerySet相當於select語句用where或limit過濾。你通過模型的Manage來獲取QuerySet,每個模型至少有一個Manage
1.1.6 檢索所有的物件
檢索表中所有資料,最簡單的方式是用all().
all_entries = Entry.objects.all()
1.1.7 過濾檢索特定物件
檢索過濾特定查詢結果,有兩個方法。
filter(**kwargs) 返回一個新的匹配查詢引數後的QuerySet
exclude(**kwargs) 返回一個新的不匹配查詢引數後的QuerySet
Entry.objects.filter(pub_date__year=2006)
1.1.8 連結過濾
Entry.objects.filter(headline__startswith='What') .exclude(pub_date__gte=datetime.now()) .filter(pub_date__gte=datetime(2005, 1, 1))
1.1.9 過濾結果集是唯一
每次你完成一個QuerySet,你獲得一個全新的結果集,不包括前面的。每次完成的結果集是可以貯存,使用或複用 q1 = Entry.objects.filter(headline__startswith="What") q2 = q1.exclude(pub_date__gte=datetime.now()) q3 = q1.filter(pub_date__gte=datetime.now())
三個QuerySets是分開的,第一個是headline以"What"單詞開頭的結果集,第二個是第一個的子集,即pub_date不大於現在的,第三個是第一個的子集 ,pub_date大於現在的
1.2.1 結果集是延遲的
QuerySets是延遲的,建立QuerySets不會觸及到資料庫操作,你可以多個過濾合併到一起,直到求值的時候django才會開始查詢。如:
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的時候,django才開始查詢執行SQL到資料庫。
1.2.2 其他的QuerySet方法
大多數情況你使用all()、filter()和exclude()
1.2.3 限制 QuerySets
使用python的陣列限制語法限定QuerySet,如:
取前5個
Entry.objects.all()[:5]
取第五個到第十個
Entry.objects.all()[5:10]
一般的,限制QuerySet返回新的QuerySet,不會立即求值查詢,除非你使用了"step"引數
Entry.objects.all()[:10:2] Entry.objects.order_by('headline')[0] Entry.objects.order_by('headline')[0:1].get()
1.2.4 欄位查詢
欄位查詢是指定SQL語句的WHERE條件從句,通過QuerySet的方法filter(), exclude()和get()指定查詢關鍵字。
基本查詢field__lookuptype=value
例如:
Entry.objects.filter(pub_date__lte='2006-01-01')
轉換為SQL:
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
如果你傳了無效的引數會拋異常
資料庫API 支援一些查詢型別,下面體驗一下:
a、exact
Entry.objects.get(headline__exact="Man bites dog")
等價於
SELECT ... WHERE headline = 'Man bites dog';
如果查詢沒有提供雙下劃線,那麼會預設 __exact=
Blog.objects.get(id__exact=14) # Explicit form Blog.objects.get(id=14) # __exact is implied
b、iexact——忽略大小寫
Blog.objects.get(name__iexact="beatles blog")
blog title會匹配 "Beatles Blog", "beatles blog", 甚至 "BeAtlES blOG".
c、contains——包含查詢,區分大小寫
Entry.objects.get(headline__contains='Lennon')
轉化為SQL
SELECT ... WHERE headline LIKE '%Lennon%';
icontains 不區分大小寫
startswith,endswith,istartswith,iendswith
前模糊匹配,後模糊匹配
1.2.5 跨關係查詢
Entry.objects.filter(blog__name__exact='Beatles Blog')
這個可以跨越你想要的深度。
反向跨關係查詢
Blog.objects.filter(entry__headline__contains='Lennon')
如果跨越多層關係查詢,中間模型沒有值,django會作為空對待不會發生異常。
Blog.objects.filter(entry__author__name='Lennon'); Blog.objects.filter(entry__author__name__isnull=True); Blog.objects.filter( entry__author__isnull=False, entry__author__name__isnull=True);
1.2.6 過濾器可參考模型欄位
目前給的例子裡,我們建立了過濾,比照模型欄位值和一個固定的值,但是如果我們想比較同一個模型裡的一個指端和另一個欄位的值,django提供F()——專門取物件中某列值的操作
from django.db.models import F Entry.objects.filter(n_pingbacks__lt=F('n_comments'))
注:n_pingbacks、n_comments為模型Entry屬性
django支援加減乘除和模計算
Entry.objects.filter(n_pingbacks__lt=F('n_comments') * 2) Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) Entry.objects.filter(author__name=F('blog__name'))
主鍵查詢捷徑
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
不僅限於__exact 查詢
# Get blogs entries with id 1, 4 and 7 Blog.objects.filter(pk__in=[1,4,7]) # Get all blog entries with id > 14 Blog.objects.filter(pk__gt=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
like語句轉義百分號
Entry.objects.filter(headline__contains='%')
轉義為
SELECT ... WHERE headline LIKE '%\%%';
1.2.7 快取查詢集
每個QuerySet都包含一個快取,以儘量減少對資料庫的訪問。理解他的工作原理很重要,可以寫出最高效的程式碼。
在最新建立的QuerySet裡,快取是空的。在第一次QuerySet被取值,因此資料庫查詢發生,django把查詢結果放入快取,並返回給請求,隨後的查詢取值會複用快取中的結果。
保持快取的思想習慣,因為如果你不正確使用查詢快取會有麻煩。例如下面例子會建立兩個QuerySet
print [e.headline for e in Entry.objects.all()] print [e.pub_date for e in Entry.objects.all()]
這樣意味著資料庫查詢會執行兩次,實際兩次資料庫載入
為了避免這個問題,簡單儲存QuerySet複用
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.
1.2.8 比較物件
比較兩個模型例項,使用python標準的運算子,兩個等號==
some_entry == other_entry some_entry.id == other_entry.id some_obj == other_obj some_obj.name == other_obj.name
1.2.9 刪除物件
刪除方法是很方便的,方法名為delete(),這個方法直接刪除物件沒有返回值
e.delete()
你也可以批量刪除物件,每個QuerySet有一個delete()方法,能刪除 QuerySet裡所有物件
1.3.1 一次修改多個物件
有時候你想給QuerySet裡所有物件的一個欄位賦予特定值,你可以使用 update()方法
例如:
# 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)
update()方法不返回任何值,QuerySet不支援save方法,如果要執行save,可以如下:
for item in my_queryset: item.save()
update也可以使用F()
# THIS WILL RAISE A FieldError Entry.objects.update(headline=F('blog__name'))
1.3.2 關係物件
當你在model裡定義一個關係時,模型例項會有一個方便的API來訪問關係物件。用本頁上面的模型舉個例子,一個Entry
物件可以得到blog物件,訪問blog屬性e.blog。
django也建立API來訪問關係物件的另一邊,一個blog物件訪問Entry列表b.entry_set.all().
1.3.3 One-to-many關係
如果一個物件有ForeignKey,這個模型例項訪問關係物件通過簡單的屬性
e = Entry.objects.get(id=2) e.blog # Returns the related Blog object.
你可以憑藉外來鍵屬性獲取和賦值,修改外來鍵值知道執行save()方法才會儲存到資料庫
e = Entry.objects.get(id=2) e.blog = some_blog e.save()
如果ForeignKey 設定了null=True 你可以賦值為None
e = Entry.objects.get(id=2) print e.blog # Hits the database to retrieve the associated Blog. print e.blog # 不會在向資料庫取; 使用快取中的值. e = Entry.objects.select_related().get(id=2) print e.blog # 不會在向資料庫取; 使用快取中的值. print e.blog # 不會在向資料庫取; 使用快取中的值. b = Blog.objects.get(id=1) b.entry_set.all() # 返回所有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() # 返回所有blog的關聯物件 # b.entries is a Manager that returns QuerySets. b.entries.filter(headline__contains='Lennon') b.entries.count()
add(obj1, obj2, ...) 增加多個關係物件
create(**kwargs) 建立新物件
remove(obj1, obj2, ...) 去除多個關係物件
clear() 清理所有關係物件
b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]
1.3.4 Many-to-many關係
e = Entry.objects.get(id=3) e.authors.all() # 返回Entry所有authors . e.authors.count() e.authors.filter(name__contains='John') a = Author.objects.get(id=5) a.entry_set.all() # 返回Author所有entry .
1.3.5 One-to-one關係
class EntryDetail(models.Model): entry = models.OneToOneField(Entry) details = models.TextField() ed = EntryDetail.objects.get(id=2) ed.entry # 返回 Entry 物件.
目錄
1.1.1 生成查詢
1.1.2 建立物件
1.1.3 儲存修改的物件
1.1.4 儲存 ForeignKey 和 ManyToManyField 欄位
1.1.5 檢索物件
1.1.6 檢索所有的物件
1.1.7 過濾檢索特定物件
1.1.8 連結過濾
1.1.9 過濾結果集是唯一
1.2.1 結果集是延遲的
1.2.2 其他的QuerySet方法
1.2.3 限制 QuerySets
1.2.4 欄位查詢
1.2.5 跨關係查詢
1.2.6 過濾器可參考模型欄位
1.2.7 快取查詢集
1.2.8 比較物件
1.2.9 刪除物件
1.3.1 一次修改多個物件
1.3.2 關係物件
1.3.3 One-to-many關係
1.3.4 Many-to-many關係
1.3.5 One-to-one關係
1.1.1 生成查詢
你建立完資料模型,django會自動提供給你資料庫抽象的API,可以建立、獲取、修改、刪除物件,本篇文件講解如何使用API。
我們參考下面模型,一個weblog:
#部落格 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) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __unicode__(self): return self.headline
1.1.2 建立物件
用python物件描述資料庫表的資料,django使用一個直觀的系統,一個模型類描述一個數據表,一個類的例項描述表的一條詳細記錄。使用模型的save()方法將物件建立到資料庫。
from mysite.blog.models import Blog b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') b.save()
只有執行save方法時,django才會執行sql把物件寫入資料庫。
1.1.3 儲存修改的物件
儲存修改仍然使用save()方法
b5.name = 'New name' b5.save()
1.1.4 儲存 ForeignKey 和 ManyToManyField 欄位
cheese_blog = Blog.objects.get(name="Cheddar Talk") entry.blog = cheese_blog #為 ManyToManyField 增加記錄 entry.save()
joe = Author.objects.create(name="Joe") entry.authors.add(joe) #為 ForeignKey 增加記錄
1.1.5 檢索物件
從資料庫裡檢索物件,可以通過模型的Manage來建立QuerySet,一個QuerySet表現為一個數據庫中物件的結合,他可以有0個一個或多個過濾條件,在SQL裡QuerySet相當於select語句用where或limit過濾。你通過模型的Manage來獲取QuerySet,每個模型至少有一個Manage
1.1.6 檢索所有的物件
檢索表中所有資料,最簡單的方式是用all().
all_entries = Entry.objects.all()
1.1.7 過濾檢索特定物件
檢索過濾特定查詢結果,有兩個方法。
filter(**kwargs) 返回一個新的匹配查詢引數後的QuerySet
exclude(**kwargs) 返回一個新的不匹配查詢引數後的QuerySet
Entry.objects.filter(pub_date__year=2006)
1.1.8 連結過濾
Entry.objects.filter(headline__startswith='What') .exclude(pub_date__gte=datetime.now()) .filter(pub_date__gte=datetime(2005, 1, 1))
1.1.9 過濾結果集是唯一
每次你完成一個QuerySet,你獲得一個全新的結果集,不包括前面的。每次完成的結果集是可以貯存,使用或複用 q1 = Entry.objects.filter(headline__startswith="What") q2 = q1.exclude(pub_date__gte=datetime.now()) q3 = q1.filter(pub_date__gte=datetime.now())
三個QuerySets是分開的,第一個是headline以"What"單詞開頭的結果集,第二個是第一個的子集,即pub_date不大於現在的,第三個是第一個的子集 ,pub_date大於現在的
1.2.1 結果集是延遲的
QuerySets是延遲的,建立QuerySets不會觸及到資料庫操作,你可以多個過濾合併到一起,直到求值的時候django才會開始查詢。如:
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的時候,django才開始查詢執行SQL到資料庫。
1.2.2 其他的QuerySet方法
大多數情況你使用all()、filter()和exclude()
1.2.3 限制 QuerySets
使用python的陣列限制語法限定QuerySet,如:
取前5個
Entry.objects.all()[:5]
取第五個到第十個
Entry.objects.all()[5:10]
一般的,限制QuerySet返回新的QuerySet,不會立即求值查詢,除非你使用了"step"引數
Entry.objects.all()[:10:2] Entry.objects.order_by('headline')[0] Entry.objects.order_by('headline')[0:1].get()
1.2.4 欄位查詢
欄位查詢是指定SQL語句的WHERE條件從句,通過QuerySet的方法filter(), exclude()和get()指定查詢關鍵字。
基本查詢field__lookuptype=value
例如:
Entry.objects.filter(pub_date__lte='2006-01-01')
轉換為SQL:
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
如果你傳了無效的引數會拋異常
資料庫API 支援一些查詢型別,下面體驗一下:
a、exact
Entry.objects.get(headline__exact="Man bites dog")
等價於
SELECT ... WHERE headline = 'Man bites dog';
如果查詢沒有提供雙下劃線,那麼會預設 __exact=
Blog.objects.get(id__exact=14) # Explicit form Blog.objects.get(id=14) # __exact is implied
b、iexact——忽略大小寫
Blog.objects.get(name__iexact="beatles blog")
blog title會匹配 "Beatles Blog", "beatles blog", 甚至 "BeAtlES blOG".
c、contains——包含查詢,區分大小寫
Entry.objects.get(headline__contains='Lennon')
轉化為SQL
SELECT ... WHERE headline LIKE '%Lennon%';
icontains 不區分大小寫
startswith,endswith,istartswith,iendswith
前模糊匹配,後模糊匹配
1.2.5 跨關係查詢
Entry.objects.filter(blog__name__exact='Beatles Blog')
這個可以跨越你想要的深度。
反向跨關係查詢
Blog.objects.filter(entry__headline__contains='Lennon')
如果跨越多層關係查詢,中間模型沒有值,django會作為空對待不會發生異常。
Blog.objects.filter(entry__author__name='Lennon'); Blog.objects.filter(entry__author__name__isnull=True); Blog.objects.filter( entry__author__isnull=False, entry__author__name__isnull=True);
1.2.6 過濾器可參考模型欄位
目前給的例子裡,我們建立了過濾,比照模型欄位值和一個固定的值,但是如果我們想比較同一個模型裡的一個指端和另一個欄位的值,django提供F()——專門取物件中某列值的操作
from django.db.models import F Entry.objects.filter(n_pingbacks__lt=F('n_comments'))
注:n_pingbacks、n_comments為模型Entry屬性
django支援加減乘除和模計算
Entry.objects.filter(n_pingbacks__lt=F('n_comments') * 2) Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) Entry.objects.filter(author__name=F('blog__name'))
主鍵查詢捷徑
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
不僅限於__exact 查詢
# Get blogs entries with id 1, 4 and 7 Blog.objects.filter(pk__in=[1,4,7]) # Get all blog entries with id > 14 Blog.objects.filter(pk__gt=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
like語句轉義百分號
Entry.objects.filter(headline__contains='%')
轉義為
SELECT ... WHERE headline LIKE '%\%%';
1.2.7 快取查詢集
每個QuerySet都包含一個快取,以儘量減少對資料庫的訪問。理解他的工作原理很重要,可以寫出最高效的程式碼。
在最新建立的QuerySet裡,快取是空的。在第一次QuerySet被取值,因此資料庫查詢發生,django把查詢結果放入快取,並返回給請求,隨後的查詢取值會複用快取中的結果。
保持快取的思想習慣,因為如果你不正確使用查詢快取會有麻煩。例如下面例子會建立兩個QuerySet
print [e.headline for e in Entry.objects.all()] print [e.pub_date for e in Entry.objects.all()]
這樣意味著資料庫查詢會執行兩次,實際兩次資料庫載入
為了避免這個問題,簡單儲存QuerySet複用
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.
1.2.8 比較物件
比較兩個模型例項,使用python標準的運算子,兩個等號==
some_entry == other_entry some_entry.id == other_entry.id some_obj == other_obj some_obj.name == other_obj.name
1.2.9 刪除物件
刪除方法是很方便的,方法名為delete(),這個方法直接刪除物件沒有返回值
e.delete()
你也可以批量刪除物件,每個QuerySet有一個delete()方法,能刪除 QuerySet裡所有物件
1.3.1 一次修改多個物件
有時候你想給QuerySet裡所有物件的一個欄位賦予特定值,你可以使用 update()方法
例如:
# 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)
update()方法不返回任何值,QuerySet不支援save方法,如果要執行save,可以如下:
for item in my_queryset: item.save()
update也可以使用F()
# THIS WILL RAISE A FieldError Entry.objects.update(headline=F('blog__name'))
1.3.2 關係物件
當你在model裡定義一個關係時,模型例項會有一個方便的API來訪問關係物件。用本頁上面的模型舉個例子,一個Entry
物件可以得到blog物件,訪問blog屬性e.blog。
django也建立API來訪問關係物件的另一邊,一個blog物件訪問Entry列表b.entry_set.all().
1.3.3 One-to-many關係
如果一個物件有ForeignKey,這個模型例項訪問關係物件通過簡單的屬性
e = Entry.objects.get(id=2) e.blog # Returns the related Blog object.
你可以憑藉外來鍵屬性獲取和賦值,修改外來鍵值知道執行save()方法才會儲存到資料庫
e = Entry.objects.get(id=2) e.blog = some_blog e.save()
如果ForeignKey 設定了null=True 你可以賦值為None
e = Entry.objects.get(id=2) print e.blog # Hits the database to retrieve the associated Blog. print e.blog # 不會在向資料庫取; 使用快取中的值. e = Entry.objects.select_related().get(id=2) print e.blog # 不會在向資料庫取; 使用快取中的值. print e.blog # 不會在向資料庫取; 使用快取中的值. b = Blog.objects.get(id=1) b.entry_set.all() # 返回所有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() # 返回所有blog的關聯物件 # b.entries is a Manager that returns QuerySets. b.entries.filter(headline__contains='Lennon') b.entries.count()
add(obj1, obj2, ...) 增加多個關係物件
create(**kwargs) 建立新物件
remove(obj1, obj2, ...) 去除多個關係物件
clear() 清理所有關係物件
b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]
1.3.4 Many-to-many關係
e = Entry.objects.get(id=3) e.authors.all() # 返回Entry所有authors . e.authors.count() e.authors.filter(name__contains='John') a = Author.objects.get(id=5) a.entry_set.all() # 返回Author所有entry .
1.3.5 One-to-one關係
class EntryDetail(models.Model): entry = models.OneToOneField(Entry) details = models.TextField() ed = EntryDetail.objects.get(id=2) ed.entry # 返回 Entry 物件.