difference between filter with multiple arguments and chain filter in django

前端 未结 9 755
[愿得一人]
[愿得一人] 2020-11-30 20:08

What is the difference between filter with multiple arguments and chain filter in django?

相关标签:
9条回答
  • 2020-11-30 20:55

    There is a difference when you have request to your related object, for example

    class Book(models.Model):
        author = models.ForeignKey(Author)
        name = models.ForeignKey(Region)
    
    class Author(models.Model):
        name = models.ForeignKey(Region)
    

    request

    Author.objects.filter(book_name='name1',book_name='name2')
    

    returns empty set

    and request

    Author.objects.filter(book_name='name1').filter(book_name='name2')
    

    returns authors that have books with both 'name1' and 'name2'

    for details look at https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships

    0 讨论(0)
  • 2020-11-30 20:57

    As you can see in the generated SQL statements the difference is not the "OR" as some may suspect. It is how the WHERE and JOIN is placed.

    Example1 (same joined table): from https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

    Blog.objects.filter(
           entry__headline__contains='Lennon', 
           entry__pub_date__year=2008)
    

    This will give you all the Blogs that have one entry with both (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008), which is what you would expect from this query.

    Result:

    Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}
    

    Example 2 (chained)

    Blog.objects.filter(
           entry__headline__contains='Lennon'
               ).filter(
           entry__pub_date__year=2008)
    

    This will cover all the results from Example 1, but it will generate slightly more result. Because it first filters all the blogs with (entry__headline__contains='Lennon') and then from the result filters (entry__pub_date__year=2008).

    The difference is that it will also give you results like:

    A single Blog with multiple entries

    {entry.headline: '**Lennon**', entry.pub_date: 2000}, 
    {entry.headline: 'Bill', entry.pub_date: **2008**}
    

    When the first filter was evaluated the book is included because of the first entry (even though it has other entries that don't match). When the second filter is evaluated the book is included because of the second entry.

    One table: But if the query doesn't involve joined tables like the example from Yuji and DTing. The result is same.

    0 讨论(0)
  • 2020-11-30 20:59

    The performance difference is huge. Try it and see.

    Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)

    is surprisingly slow compared to

    Model.objects.filter(condition_a, condition_b, condition_c)

    As mentioned in Effective Django ORM,

    • QuerySets maintain state in memory
    • Chaining triggers cloning, duplicating that state
    • Unfortunately, QuerySets maintain a lot of state
    • If possible, don’t chain more than one filter
    0 讨论(0)
提交回复
热议问题