Я не должен использовать цикл for, если у меня другой подход, верно? чтобы избежать большого o (n)? так вот что у меня есть.
models.py
class Drama(models.Model):
name = models.CharField(max_length=255)
views.py
def index(request):
theOffice = Drama.objects.filter(name='The Office')
return render(request, 'index.html', {
'theOffice':theOffice,
})
а теперь в шаблоне
{{ theOffice.name }}
приведенное выше ничего не отображает, что меня действительно беспокоит, так это если я использую цикл for, он работает,
{% for theOffi in theOffice %}
{{ theOffi.name }}
{% endfor %}
Но тогда какой смысл использовать фильтр? Я могу просто получить objects.all () и использовать
{% if drama.name == "the office %}
я что-то упускаю? Я действительно смущен
Ключевым моментом здесь является понимание того, что такое n
в вашем O(n)
. Когда вы перебираете objects.all()
, n
- это общее количество объектов. Когда вы перебираете objects.filter()
, n
- это количество объектов соответствие, которое намного меньше. (Конечно, у filter
есть своя стоимость, но если ваш бэкэнд не является тупым списком или эквивалентом, стоимость намного ниже линейной, так что это все равно выигрыш.)
@abarnert, в чем разница между фильтром и временем, вы знаете? Я знаю, что получить только один, я хочу его использовать, но он дает мне, если у меня нет подходящего значения в db
Фильтр возвращает массив. If you use Drama.objects.filter(name='The Office')[0]
ваш код будет работать
Если вы хотите получить один предмет, используйте .get()
вместо filter()
и [0]
.
@KlausD. получить быстрее?
@KlausD. потому что он вообще не использует цикл?
Да будет быстрее. Но ни цикл из одного элемента, ни .get()
никогда не дойдут до стоимости задействованного SQL-запроса. Если вы хотите повысить производительность, вам сначала нужно ответить на разные вопросы.
Наборы запросов Django лениво оцениваются. При нарезке наборов запросов выполняется ограничение (и / или) смещение в базе данных SQL. docs.djangoproject.com/en/2.1/ref/models/querysets/…docs.djangoproject.com/en/2.1/topics/db/queries/…
Повторение и тестирование всех элементов занимает линейное время. Если у вас есть, скажем, миллион элементов, потребуется 1 миллион сравнений, даже если совпадают только 5 из них.
Цикл по результату filter
не требует нет линейного времени.
filter
может использовать базовую базу данных или другой бэкэнд, чтобы найти только совпадающие элементы. Как правило, это лучше, чем линейное время - например, с типичной базой данных, где значения являются индексами в b-дереве со средней шириной 10, она может найти 5 совпадений в сравнениях log(1_000_000, 10) + 5 = 11
. Что намного лучше, чем 1 миллион.
Поскольку может быть 5 совпадений - или 0, или 20 - вы все равно получите QuerySet
- итерацию, которую вам нужно перебрать. Но вы перебираете только 5 совпадений, а не 1 миллион элементов, поэтому ваша общая сложность равна 11 + 5 = 16
, что все равно намного лучше, чем 1 миллион.
Если вы точно знаете, что всегда будет ровно одно совпадение, вам даже не нужно их перебирать; просто используйте первый с Drama.objects.filter(name='The Office')[0]
. Затем выполняется 6 сравнений.
По сравнению с шагами 6 + 1 = 7
с циклом, эти 6 шагов не являются большой оптимизацией. Но вы делаете это не для этого; вы делаете это для простоты и правильности:
фильтр возвращает
QuerySet[]
.