1. 程式人生 > >Django:Model的Filter

Django:Model的Filter

django model filter 條件過濾,及多表連線查詢、反向查詢,某欄位的distinct

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.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__bb='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範圍內 
__startswith 以...開頭 
__istartswith 以...開頭 忽略大小寫 
__endswith 以...結尾 
__iendswith 以...結尾,忽略大小寫 
__range 在...範圍內 
__year 日期欄位的年份 
__month 日期欄位的月份 
__day 日期欄位的日 
__isnull=True/False 
例子: 
>> 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") 
即q1.filter(pub_date__gte=datetime.date.today())表示為時間>=now,q1.exclude(pub_date__gte=datetime.date.today())表示為<=now 
2013/12/12補充: 
“在django models中取得一個欄位的distinct值”。就是select distinct xxx from table_name ...這樣的功能。使用values會生成ValuesQuerySet(形如N個dict組成的list),猜測大資料無額外效能影響,畢竟queryset系列都是使用時才查詢操作的。 
xxxx.objects.values("field_name").distinct() 
#或者 
xxxx.objects.distinct().values("field_name") 
這兩句生成的sql語句相同,原帖地址:

http://blog.csdn.net/tsbob/article/details/1340293。 
關於快取: 
queryset是有快取的,a = A.objects.all(),print [i for i in a].第一次執行列印會查詢資料庫,然後結果會被儲存在queryset內建的cache中,再執行print的時候就會取自快取。
很多時候會遇到僅需判斷queryset是否為空的情況,可以1. if queryset:pass 2.if queryset.count>0:pass 3.if queryset.exists():pass. 三種方式效能依次提升。 
當queryset非常巨大時,cache會成為問題。此時可以queryset.iterator(),迭代器的用處就不多說了,根據具體需求情況使用。