Django 5 для начинающих

Прогресс по курсу:  9/1004

3.5 Django ORM, методы возвращающие QuerySet
3 из 9 шагов пройдено
0 из 30 баллов  получено

Для начала создадим еще одно приложение, чтобы мы могли рассмотреть как можно больше методов.

Создадим новое приложение в нашем проекте:

python manage.py startapp orm_method

И добавим модели в приложение orm_method.

from django.db import models
from django.utils import timezone


class Worker(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    age = models.SmallIntegerField(null=True)
    created = models.DateTimeField(default=timezone.now)
    work_experience = models.SmallIntegerField(default=0)

Зарегистрируем приложение в INSTALLED_APPS и выполним миграции.

python manage.py makemigrations
python manage.py migrate

Запустим шелл, импортируем модели:

python manage.py shell
from orm_method.models import Worker

Заполним таблицу: 

Worker.objects.create(first_name='Roger',   last_name='Campbell',  age=25, work_experience=5)
Worker.objects.create(first_name='John',    last_name='Rodriguez', age=31, work_experience=3)
Worker.objects.create(first_name='Ryan',    last_name='Medina',    age=43)
Worker.objects.create(first_name='Michael', last_name='Smith',     age=28, work_experience=3)
Worker.objects.create(first_name='Steven',  last_name='Bryant',    age=33, work_experience=7)
Worker.objects.create(first_name='Jessie',  last_name='Smith',     age=29, work_experience=2)
Worker.objects.create(first_name='Ted',     last_name='Murphy',    age=34)

Теперь мы можем приступить к изучению методов возвращающих QuerySet.

all()

Начнем с самого простого метода. Он возвращает объект QuerySet, который содержит все объекты из таблицы.

Worker.objects.all()

Вы можете использовать нотацию срезов Python для нарезки QuerySet.

 

filter()

Начнем с самого простого фильтра. Вы можете фильтровать с помощью одного поискового условия:

Worker.objects.filter(last_name='Smith')

Мы выбрали работников с фамилией Smith.

А также вы можете фильтровать с несколькими поисковыми условиями:

Worker.objects.filter(last_name='Smith', age=28)

В обоих вышеуказанных случаях Django переводит поисковые условия в предложение SQL WHERE.

 

 exclude()

Можно исключить некоторые результаты из запроса с помощью метода exclude().

Worker.objects.exclude(first_name='John')

Мы получили всех работников, кроме работников с именем John.


  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

Извлекать объекты вида <Worker: Worker object (1)> чрезвычайно тоскливо и неинформативно.
Ничто не мешает определить в модели метод __str__(self), и в нем показать основные атрибуты.
Например, так:

    def __str__(self):
        return f"{self.first_name} {self.last_name} ({self.age} years old) #{self.id}"

И результаты запросов "заиграют новыми красками": <Worker: Roger Campbell (25 years old) #1> вместо стандартного.
ПРИМЕЧАНИЕ: включение конкретных полей в __str__() влияет на запросы, выполняемые Django. Так, если будет применен метод only('first_name'), вывод объекта с помощью __str__() в варианте выше приведет к выполнению дополнительных запросов. Поэтому лучше ограничиться этим подходом в учебных целях.

Ну и совсем уж странно выполнять запросы "в слепую", не видя, какой SQL код генерирует Django. Конечно, можно использовать метод, предложенный авторами курса ранее - импортировать connection, и смотреть генерируемые запросы в connection.queries, но это неудобно.

Есть гораздо более "прямой" способ:

1. Установить django-extensions:

pip install django-extensions

2. Добавить django-extensions в INSTALLED_APPS:

INSTALLED_APPS = [
# удалил стандартные строки
    'django_extensions',  # Эту строку вставить в список
    'orm_method',         # До наших приложений, с которыми работаем - это для примера
]

3. Вместо python manage.py shell запускать shell_plus с опцией --print-sql:

python manage.py shell_plus --print-sql

Если при попытке запустить команду выше отображается ошибка, что django-extensions не найден, нужно выполнить миграцию - не знаю почему, но это помогает, хотя при этом отображается сообщение, что мигрировать нечего.

Это позволит
а) не импортировать пользовательские модели - они импортируются сами
б) видеть SQL запросы сразу (когда они выполняются Django)

Предлагаю сравнить вывод в примере exclude() выше и это:

 

Жаль, что авторы курса не сделали этот вариант работы с ORM стандартным...

Изменен ilya kutaev

@ilya_kutaev, Спасибо за подробный коммент, было полезно. А какая IDE у вас используется, что так красиво в цветах выводит? У меня в PyCharm в Windows PowerShell унылое черно-белое отображение... )))

@Максим_Михеев, Тот же PyCharm в Win10, но PS я дополнительно не подключал (вернее, не менял настройки по умолчанию)

Изменен ilya kutaev

@ilya_kutaev, Если не сложно, покажите что у вас в настройках терминала PyCharm:

@Максим_Михеев, Все точно то же самое, только настройка Shell по умолчанию - я некорректно написал выше, я ее не изменял

Меня вводило в заблуждение это сообщение - возникает ощущение, что нужно установить PS, хотя он уже и используется:

М.б. версия PyCharm различается?

Изменен ilya kutaev

@ilya_kutaev, Один в один такая же. Подозреваю что у меня почему-то не работает цветовая схема...

@ilya_kutaev, роскошно, спасибо

@ilya_kutaev, В общем выяснил в чем была проблема, у меня не был установлен пакет IPython, после его установки все стало в цвете как у вас! (помогла техподдержка JetBrains)

@Максим_Михеев, Я разобрался, почему иногда не находится django-extensions.

2. Добавить django-extensions в INSTALLED_APPS:

INSTALLED_APPS = [
# удалил стандартные строки
    'django_extensions',  # Эту строку вставить в список
    'orm_method',         # До наших приложений, с которыми работаем - это для примера
]

Если при попытке запустить команду выше отображается ошибка, что django-extensions не найден, нужно выполнить миграцию - не знаю почему, но это помогает, хотя при этом отображается сообщение, что мигрировать нечего.

Это из-за того, что легко ошибиться и написать "-" вместо "_" в названии приложения - именно так я и сделал несколько раз ))) 

Это видно в сообщении об ошибке - название указано с дефисом. Причем тут миграции я не знаю, видимо, кроме них я еще и заменил строку на корректную

Изменен ilya kutaev

И ещё хотел бы оставить не большую подсказку для начинающих ребят о том, что делать, если удалили поле из таблицы, при автоматическом инкрементировании, когда id автоматически растет (когда даже после удаления всех строк в таблице мы добавляем новый объект, а id у этого объекта начинается не с одного) для решения подобных проблем я бы советовал вам иметь редакторы баз данных, например как по курсу сейчас мы используем SQLiteStudio(в разных реляционных базах данных запросы могут быть разными).Так вот, чтобы нам сбросить id нужно в редакторе SQLiteStudio написать и выполнить следующую команду: DELETE FROM sqlite_sequence WHERE name='имя_вашей_таблицы' и теперь после каждой очистки таблицы вы можете выполнять эту команду для сброса id

хотел бы задать вопрос по поводу переменной TIME_ZONE = 'UTC' , что это за универсальное время, надо ли его менять в каких-то случаях на свое локальное при работе с Django? Вопрос возник в ходе работой с бд, когда я увидел, что время локальное и время добавление объектов в таблице не сходится.

@Шамбер_Егор, можно установить свой часовой пояс, например 'Europe/Moscow', их список: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

а есть ли возможность как-то в методе filter искать, например, по двум именам ?

@Дмитрий_Чекмасов, Да, можем через метод in, его мы рассмотрим в разделе 3.7, а также через Q объекты, их мы рассматриваем во втором курсе.

@Дмитрий_Чекмасов, вот пример фильтрации по двум именам:

спасибо, вперед чуть забежал значит )