Django 1.0中国語ドキュメント---クエリーの実行
クエリーの生成
データモデルを作成すると、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
オブジェクトの作成
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を実行してオブジェクトをデータベースに書き込む.
変更したオブジェクトを保存
変更を保存するにはsave()メソッドを使用します.
>> b5.name = 'New name'
>> b5.save()
ForeignKeyフィールドとManyToManyFiledフィールドの保存
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
ManyToManyFiledのレコードを追加
>> joe = Author.objects.create(name="Joe")
>> entry.authors.add(joe)
オブジェクトの取得
データベースからオブジェクトを検索すると、モデルのManageによってQuerySetを確立することができ、1つのquerysetは1つのデータベースのオブジェクトの結合として表現され、彼は0つの1つ以上のフィルタ条件を持つことができ、SQLでQUERYSETはSELECT文に相当してWHEREまたはLIMITでフィルタリングされる.
モデルのmanagerでQUERYSETを取得します.各モデルには少なくとも1つのmanagerがあります.
>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback:
...
AttributeError: "Manager isn't accessible via Blog instances."
すべてのオブジェクトを取得
テーブル内のすべてのデータを検索する最も簡単な方法はall()である.
>>> all_entries = Entry.objects.all()
フィルタによる特定のオブジェクトの取得
特定のクエリーのフィルタ結果を取得するには、2つの方法があります.
filter(**kwargs)は、新しいマッチングパラメータを返した後のQuerySet
Exclude(**kwargs)は、新しい不一致クエリーパラメータを返した後のQuerySet
例:
Entry.objects.filter(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を完備するたびに、前のものを含まない新しい結果セットを得ることができます.完了するたびに結果セットを保存、使用、または多重化できます.
>> q1 = Entry.objects.filter(headline__startswith="What")
>> q2 = q1.exclude(pub_date__gte=datetime.now())
>> q3 = q1.filter(pub_date__gte=datetime.now())
3つのQuerySetsは別々で、1つ目はheadlineが「What」単語で始まる結果セットで、2つ目は1つ目のサブセット、すなわちpub_dateは現在のものより大きくなく、3番目は1番目のサブセット、pub_dateが現在より大きい
結果セットは遅延します
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
3つのフィルタ条件が実行されているように見えますが、実際にprint qが最後に実行されたとき、djangoはSQLをデータベースにクエリーし始めました.
その他のQuerySetメソッド
ほとんどの場合、all()、filter()、exclude()を使用します.
QuerySetsの制限
pythonの配列制限構文を使用して、次のようなQuerySetを定義します.
上位5
>>> Entry.objects.all()[:5]
5番目から10番目を取る
>>> 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()
フィールド検索
フィールド検索は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はいくつかのクエリータイプをサポートしています.
exact
Entry.objects.get(headline__exact="Man bites dog")
SQLに変換:
SELECT ... WHERE headline = 'Man bites dog';
クエリに二重アンダースコアが指定されていない場合は、デフォルトの_exact=
>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
iexact
大文字と小文字を無視
Blog.objects.get(name__iexact="beatles blog")
blog titleは「Beatles Blog」、「beatles blog」、さらには「BeAtlES blOG」と一致する.
contains
クエリーを含める、大文字と小文字を区別する
Entry.objects.get(headline__contains='Lennon')
SQLに変換
SELECT ... WHERE headline LIKE '%Lennon%';
icontains大文字と小文字を区別しない
startswith , endswith,istartswith , iendswith
フロントブラーマッチング、ポストブラーマッチング
相互関係クエリー
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つの指端と別のフィールドの値を比較したい場合,djangoはF()を提供する.
>>> from django.db.models import F
>>> Entry.objects.filter(n_pingbacks__lt=F('n_comments'))
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
に限らずExcactクエリー
# 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 '%\%%';
キャッシュ・クエリー・セット
各QuerySetには、データベースへのアクセスを最小限に抑えるためのキャッシュが含まれています.彼の動作原理を理解することが重要で、最も効率的なコードを書くことができます.
新しく作成されたQuerySetではキャッシュが空です.1回目のQuerySetで値が取られるため、データベースクエリが発生し、djangoはクエリ結果をキャッシュに入れ、リクエストに返し、その後のクエリ値はキャッシュ内の結果を多重化します.
クエリー・キャッシュを正しく使用しないと面倒になるので、キャッシュの習慣を維持します.たとえば次の例では、2つのQuerySetが作成されます.
>>> print [e.headline for e in Entry.objects.all()]
>>> print [e.pub_date for e in Entry.objects.all()]
これは、データベース・クエリーが2回実行され、実際には2回のデータベース・ロードが実行されることを意味します.
この問題を回避するために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.
Qオブジェクトによる複合クエリー
キーワードクエリーはfilterを使用してandセットで、もしあなたがもっと多くの複合クエリーを実行したいならば“or”のようにQオブジェクトをすることができます.
Qオブジェクト(django.db.models.Q)は、キーワードセットパッケージのパラメータです.
たとえば
Q(question__startswith='What')
Qオブジェクトは&と|リンクを使用できます
例えばORクエリ
Q(question__startswith='Who') | Q(question__startswith='What')
以下のSQLに相当
WHERE question LIKE 'Who%' OR question LIKE 'What%'
Qオブジェクトの使用をキャンセルします~
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
複数のQオブジェクトを転送可能
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
SQLに翻訳
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
オブジェクトの比較
2つのモデルインスタンスを比較し、python標準の演算子を使用し、2つの等号==
>>> some_entry == other_entry
>>> some_entry.id == other_entry.id
>>> some_obj == other_obj
>>> some_obj.name == other_obj.name
オブジェクトの削除
削除方法は便利で、方法名はdelete()で、この方法は直接オブジェクトを削除して値を返さない.
たとえば
e.delete()
オブジェクトを一括削除することもできます.QuerySetごとにdelete()メソッドがあり、QuerySet内のすべてのオブジェクトを削除することができます.
例:pub_を削除するdateは2005年の対象
複数のオブジェクトを一度に変更
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'))
リレーショナルオブジェクト
モデルで関係を定義すると、モデルインスタンスには関係オブジェクトにアクセスするための便利なAPIがあります.このページの上のモデルで例を挙げて、Entry
オブジェクトはblogオブジェクトを取得し、blogプロパティe.blogにアクセスできます.
djangoもAPIを作成してリレーショナルオブジェクトの反対側にアクセスし、1つのblogオブジェクトがEntryリストb.entry_にアクセスするset.all() .
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)
>>> 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 # ; .
>>> 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]
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 .
One-to-one関係
class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField()
ed = EntryDetail.objects.get(id=2)
ed.entry # Entry .