"&" и "|" против "and" и "or" для операторов "AND" и "OR" в Django
 У меня есть Blog модель ниже. * Я использую Django 3.2.16 и PostgreSQL:
# "store/models.py"
from django.db import models
class Blog(models.Model):
    post = models.TextField()
    
    def __str__(self):
        return self.post
 Тогда, store_blog таблица имеет 2 строки ниже:
store_blog таблица:
| id | post | 
|---|---|
| 1 | Python is popular and simple. | 
| 2 | Java is popular and complex. | 
Тогда, при выполнении  кода filter() с использованием & или Q() и &. или используя and или Q() и and в test() представлении, как показано ниже: 
# "store/views.py"
from .models import Blog
from django.db.models import Q
def test(request):
    # With "&"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") & \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "&"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") & 
                      Q(post__contains="simple"))
    print(qs)              # ↑ Here
    # With "and"
                                                      # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") and \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "and"
                           # ↓ Here                     # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") and 
                      Q(post__contains="simple"))
    print(qs)              # ↑ Here
    return HttpResponse("Test")
Я получил тот же результат, что и ниже:
<QuerySet [<Blog: Python is popular and simple.>]> # With "&"
<QuerySet [<Blog: Python is popular and simple.>]> # With "Q()" and "&"
<QuerySet [<Blog: Python is popular and simple.>]> # With "and"
<QuerySet [<Blog: Python is popular and simple.>]> # With "Q()" and "and"
[22/Dec/2022 16:04:45] "GET /store/test/ HTTP/1.1" 200 9
 И, при выполнении  кода filter() с использованием | или Q() и | или используя or или Q() и or в test() представлении, как показано ниже: 
# "store/views.py"
from .models import Blog
from django.db.models import Q
def test(request):
    # With "|"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") | \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "|"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") | 
                             Q(post__contains="simple"))
    print(qs)              # ↑ Here
    # With "or"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") or \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "or"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") or 
                             Q(post__contains="simple"))
    print(qs)              # ↑ Here
    return HttpResponse("Test")
Я получил тот же результат, что и ниже:
<QuerySet [<Blog: Python is popular and simple.>, <Blog: Java is popular and complex.>]> # With "|"
<QuerySet [<Blog: Python is popular and simple.>, <Blog: Java is popular and complex.>]> # With "Q()" and "|"
<QuerySet [<Blog: Python is popular and simple.>, <Blog: Java is popular and complex.>]> # With "or"
<QuerySet [<Blog: Python is popular and simple.>, <Blog: Java is popular and complex.>]> # With "Q()" and "or"
[22/Dec/2022 16:20:27] "GET /store/test/ HTTP/1.1" 200 9
 Итак, есть ли различия между & и and и | и or для AND и OR операторов  в Django? 
Ваши тестовые данные совершенно недостаточны для этого теста, поскольку обе строки содержат popular. (То есть, все, что может найти popular, эквивалентно Blog.objects.all().)
В любом случае, булевы or и and здесь работают неправильно (поскольку они просто выполняют булеву оценку), но вы просто не замечаете этого из-за вышеизложенного.
Вам  необходимо  использовать  операторы "bitwise" | / & / ^, как указано в документации. ("bitwise" в кавычках, так как класс Q перегружает операторы, чтобы они не были bitwise вообще.)
Для доказательства рассмотрим Q изолированно, ничего не запрашивая...
>>> from django.db.models import Q
>>> pop = Q(post__contains="popular")
<Q: (AND: ('post__contains', 'popular'))>
>>> sim = Q(post__contains="simple")
<Q: (AND: ('post__contains', 'simple'))>
>>> pop and sim
<Q: (AND: ('post__contains', 'simple'))>
# ^ incorrect; evaluates to `sim`
>>> pop & sim
<Q: (AND: ('post__contains', 'popular'), ('post__contains', 'simple'))>
# ^ correct: combines the two q:s with `and`
>>> pop or sim
<Q: (AND: ('post__contains', 'popular'))>
# ^ incorrect; evaluates to `pop`
>>> pop | sim
<Q: (OR: ('post__contains', 'popular'), ('post__contains', 'simple'))>
# ^ correct: combines the two q:s with `or`
При выполнении кода filter() с использованием & или Q() и & или используя and или Q() и and в test() представлении, как показано ниже: 
# "store/views.py"
from .models import Blog
from django.db.models import Q
from django.http import HttpResponse
def test(request):
    # With "&"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") & \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "&"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") & 
                      Q(post__contains="simple"))
    print(qs)              # ↑ Here
    # With "and"
                                                      # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") and \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "and"
                           # ↓ Here                     # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") and 
                      Q(post__contains="simple"))
    print(qs)              # ↑ Here
    return HttpResponse("Test")
& или Q() и & могут выполнять AND операторы  в соответствии с  журналами запросов PostgreSQL, как показано ниже. *Вы можете проверить  на PostgreSQL, как регистрировать запросы с транзакционными запросами, такими как "BEGIN" и "COMMIT":
 И, при выполнении  кода filter() с использованием | или Q() и | или используя or или Q() и or в test() представлении, как показано ниже: 
# "store/views.py"
from .models import Blog
from django.db.models import Q
from django.http import HttpResponse
def test(request):
    # With "|"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") | \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "|"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") | 
                             Q(post__contains="simple"))
    print(qs)              # ↑ Here
    # With "or"
                                                     # ↓ Here
    qs = Blog.objects.filter(post__contains="popular") or \
         Blog.objects.filter(post__contains="simple")
    print(qs)
    # With "Q()" and "or"
                           # ↓ Here                    # ↓ Here
    qs = Blog.objects.filter(Q(post__contains="popular") or 
                             Q(post__contains="simple"))
    print(qs)              # ↑ Here
    return HttpResponse("Test")
| или Q() и | могут выполнять OR операторы  согласно  журналам запросов PostgreSQL как показано ниже:

