JavaRush /Курси /Модуль 3: Django /Використання методів all(), filter(), get() в Django ORM

Використання методів all(), filter(), get() в Django ORM

Модуль 3: Django
Рівень 8 , Лекція 6
Відкрита

У цій лекції ми зануримося в можливості роботи з даними та більш детально розглянемо методи all(), filter() та get() у Django ORM.

Навіщо нам all(), filter() і get()?

Обробка даних у додатку потребує функціональних і зручних інструментів для отримання інформації. Методи all(), filter() і get() є основоположними для взаємодії з базою даних через ORM.

Може виникнути закономірне питання: а чому б нам просто не писати сирі SQL-запити? Це можливо, але:

  • Їх складно підтримувати: уявіть, що бізнес-логіка змінюється. Що тоді? Ручний рефакторинг SQL-запитів!
  • Це ненадійно: за безпеку має відповідати ORM, а не доводити себе до нервового тику від SQL-ін'єкцій.
  • Та ще й нудно! Django ORM дає вам Python, а не SQL. Навіщо ускладнювати собі життя?

Метод all()

Метод all() використовується для отримання всіх записів з таблиці, пов'язаної з моделлю.

Приклад використання

# Модель для прикладу
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=100)
    published_year = models.IntegerField()

Отримаємо всі книги з бази даних:

# Отримання всіх записів
books = Book.objects.all()

# Перегляд результату
for book in books:
    print(f"{book.title} — {book.author}, {book.published_year}")

Особливості

  1. all() повертає QuerySet. Це означає:
    • Він лінивий (лінується виконувати запити, поки ти до нього не звернешся).
    • Можна використовувати ланцюжки методів (наприклад, комбінувати з filter() чи order_by()).
  2. Якщо в таблиці немає даних, повернеться порожній QuerySet, а не None.

Приклад ланцюжка методів

Додамо сортування одразу після методу all():

# Отримання всіх книг за спаданням року публікації
books = Book.objects.all().order_by('-published_year')

for book in books:
    print(f"{book.title} — {book.published_year}")

Метод filter()

filter() використовується для отримання записів, що відповідають одній або кільком умовам.

Приклади використання

  1. Фільтрація за одним полем:
    # Знайти всі книги автора "Дмитро Глуховський"
    books = Book.objects.filter(author="Дмитро Глуховський")
    
    for book in books:
        print(book.title)
  1. Фільтрація за кількома умовами:
    # Знайти книги автора "Дмитро Глуховський", опубліковані після 2005 року
    books = Book.objects.filter(author="Дмитро Глуховський", published_year__gt=2005)
    
    for book in books:
        print(book.title)
  1. Використання складних умов з Q (з попередньої лекції ти напевно пам'ятаєш Q):
    from django.db.models import Q
    
    # Знайти книги, опубліковані до 2000 року або написані автором "Лев Толстой"
    books = Book.objects.filter(Q(published_year__lt=2000) | Q(author="Лев Толстой"))
    
    for book in books:
        print(book.title)
    
    

Особливості

  • filter() повертає QuerySet (аналогічно all()).
  • Якщо в таблиці немає записів, що відповідають умовам, повернеться порожній QuerySet.

Метод get()

get() витягує рівно один запис, який відповідає заданим умовам.

Приклад використання

  1. Отримання запису за ID:
    # Знайти книгу з ID = 5
    book = Book.objects.get(id=5)
    print(book.title)
  1. Фільтрація за полями моделі:
    # Знайти книгу з назвою "1984" і автором "Джордж Орвелл"
    book = Book.objects.get(title="1984", author="Джордж Орвелл")
    print(f"{book.title} — {book.author}")

Важлива різниця: get() vs filter()

  • get() повертає один об'єкт моделі (а не QuerySet).
  • Якщо запис не знайдено, кидається виняток DoesNotExist. Будь уважним — краще обертати в try...except:
    try:
        book = Book.objects.get(id=9999)  # ID, якого немає
    except Book.DoesNotExist:
        print("Такої книги немає!")
    
  • Якщо умовам відповідає більше одного запису, ти отримаєш MultipleObjectsReturned. Ось тобі ще одна причина не використовувати get() без впевненості!

Коли використовувати get()?

Використовуй його тільки тоді, коли впевнений, що запит поверне рівно один запис. В інших випадках filter() безпечніше.

Відмінності між all(), filter() та get()

Метод Повертає Коли використовувати
all() QuerySet, всі записи Коли потрібно отримати повний список даних
filter() QuerySet, записи за умовою Для вибірки записів, що відповідають одній або декільком умовам
get() Один об'єкт моделі Для отримання одного конкретного об'єкта, якщо впевнені, що він існує

Кращі практики та типові помилки

  1. Ліниве завантаження:

    методи all() та filter() повертають лінивий QuerySet. Якщо ти випадково не "матеріалізував" QuerySet (наприклад, перебрав його в циклі), SQL-запит просто не виконається. Щоб перевірити запит, можна скористатися методом .query:
    books = Book.objects.filter(author="Дмитро Глуховський")
    print(books.query)  # Друкує SQL-запит
    
  2. Використання get() на невідповідний запит: ніколи не використовуй get(), якщо запит може повернути більше одного запису. Наприклад:

    # Це викличе MultipleObjectsReturned, якщо є дві однакові книги
    book = Book.objects.get(author="Лев Толстой")
  3. Обробка порожніх результатів: завжди перевіряй результат виклику filter() або all() на наявність записів перед виконанням операцій:

    books = Book.objects.filter(author="Невідомий автор")
    if not books.exists():
        print("Книги не знайдені!")
    

Застосування на практиці

Давайте додамо в наш додаток просту функціональність. Уявіть, що нам потрібно реалізувати пошук книг для бібліотеки.

Крок 1: Створюємо представлення

# views.py

from django.shortcuts import render
from .models import Book

def search_books(request):
    query = request.GET.get('q', '')  # Отримати пошуковий запит від користувача
    books = Book.objects.filter(title__icontains=query)  # Фільтр за заголовком
    return render(request, 'search_results.html', {'books': books, 'query': query})

Крок 2: Додаємо URL-маршрут

# urls.py

from django.urls import path
from .views import search_books

urlpatterns = [
    path('search/', search_books, name='search_books'),
]

Крок 3: Створюємо простий шаблон

<!-- templates/search_results.html -->

<form method="get" action="{% url 'search_books' %}">
    <input type="text" name="q" placeholder="Шукати...">
    <button type="submit">Пошук</button>
</form>

<h2>Результати пошуку для "{{ query }}"</h2>

<ul>
    {% for book in books %}
        <li>{{ book.title }} — {{ book.author }}</li>
    {% empty %}
        <p>Нічого не знайдено</p>
    {% endfor %}
</ul>

Тепер наша бібліотека може шукати книги за назвою з використанням filter()!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ