Модуль 23

Робота з користувацькою моделлю User

Це чудовий виклик! Давайте створимо цей урок. Я використаю контекст Django (Python), оскільки саме там термін "Custom User Model" є найбільш значущим, а проблеми, пов'язані з ним — класикою веб-розробки. Але логіка буде зрозуміла навіть тим, хто працює з іншими фреймворками.

Ось ваш урок у стилі CS50.


🎓 Урок: Робота з користувацькою моделлю (Custom User Model)

👋 Усім привіт! Я радий вас бачити.

Сьогодні ми поговоримо про дещо фундаментальне. Про те, що є серцем майже будь-якого сучасного веб-застосунку. Ми говоримо про Користувача (User).

Але не просто про якогось абстрактного юзера, а про те, як взяти контроль над ним у свої руки.


1. 🔥 Вступ: Чому стандартного паспорта замало?

Уявіть, що ви будуєте новий житловий комплекс. У вас є стандартна форма реєстрації мешканців, яку вам видала держава (читай: фреймворк). У цій формі є поля: * Ім'я * Прізвище * Пароль (ключ від дверей)

Це чудово працює, якщо ви будуєте гуртожиток. Але що, як ви будуєте елітний клуб? Вам потрібно знати: * Чи є у мешканця собака? (щоб пустити на майданчик) * День народження? (щоб надіслати листівку) * Номер телефону? (для екстреного зв'язку) * Чи є він VIP-клієнтом?

Стандартна форма ("User", який йде в коробці з інструментом) не має цих полів.

Питання до вас: Що робити? Створювати окрему таблицю в Excel під назвою "Додаткова інфа" і намагатися склеїти її з основною? Чи, можливо, одразу переписати бланк реєстрації під свої потреби, поки ми ще не залили фундамент?

Чому без цього не обійтись: У 99% реальних проєктів стандартного користувача (username + password) недостатньо. Якщо ви не створите власну модель користувача на самому початку проєкту, то пізніше, коли у вас вже буде база даних із тисячами людей, змінити це буде так само боляче, як замінити фундамент у вже збудованому хмарочосі.

Тож сьогодні ми навчимося робити це правильно. Одразу.


2. 🧠 Теоретична база: Що там "під капотом"?

Давайте заглянемо всередину.

У більшості фреймворків (наприклад, Django) вже є готова таблиця в базі даних, яка називається auth_user. Розробники фреймворку написали її за вас. Це зручно.

Але Custom User Model (Користувацька модель) — це коли ми кажемо фреймворку:

"Слухай, дякую за твою таблицю, але я хочу використовувати СВОЮ. У ній будуть ті самі поля, що й у тебе, ПЛЮС мої власні".

Два шляхи (інтуїтивне розуміння):

  1. Шлях "Наслідування" (AbstractUser): Ви берете готовий шаблон користувача і просто дописуєте туди нові поля (телефон, аватарка). Це як взяти типовий проєкт будинку і додати до нього гараж.
    • Використовуємо у 90% випадків.
  2. Шлях "З нуля" (AbstractBaseUser): Ви кажете: "Мені не треба ні ім'я, ні прізвище, я хочу входити за відбитком пальця або номером телефону". Ви будуєте все з нуля.
    • Використовуємо тільки в дуже специфічних випадках.

🔑 Що треба запам'ятати залізно:

Створювати власну модель User треба ДО того, як ви запустите першу міграцію (створите перші таблиці в базі даних).

Логіка проста: 1. Описуємо Клас (креслення). 2. Кажемо Системі: "Використовуй МОЄ креслення замість стандартного" (в налаштуваннях). 3. Створюємо таблиці.


3. 🧪 Приклади: Від простого до реального

Давайте кодити. Ми візьмемо за основу Django, бо це класичний приклад, але логіка однакова всюди.

Приклад 1: Мінімальний старт (Те, що треба зробити завжди)

Навіть якщо ви поки що не знаєте, які поля вам треба, зробіть "пустишку".

from django.contrib.auth.models import AbstractUser
from django.db import models

# Ми наслідуємося від стандартного AbstractUser
class User(AbstractUser):
    pass 
    # Поки що пусто. Але це вже НАШ клас!

Очікування студента: "Ну і що змінилося? Нічого ж немає." Реальність: Ми виграли свободу. Тепер, якщо через місяць замовник скаже "додай поле для Telegram ID", ми просто допишемо його сюди. Якби ми використовували стандартний User, нам довелося б страждати.


Приклад 2: Реальний проєкт (Додаємо м'ясо)

Уявімо, що ми робимо соцмережу для розробників. Нам треба знати їхній GitHub та статус "шукаю роботу".

class User(AbstractUser):
    # Стандартні поля (username, email) вже тут є "під капотом"

    bio = models.TextField("Про себе", blank=True)
    github_link = models.URLField(blank=True)
    is_looking_for_job = models.BooleanField(default=False)

    # Магія: перевизначаємо строкове представлення
    def __str__(self):
        return f"{self.username} (Job: {self.is_looking_for_job})"

Запитання: Що буде, якщо ми виведемо список усіх юзерів у консолі? Відповідь: Замість нудних User object (1), ми побачимо: david_malan (Job: False). Інформативно!


Приклад 3: Налаштування системи (AUTH_USER_MODEL)

Це той крок, про який забувають новачки. Ми написали клас, але система про нього не знає.

У файлі налаштувань (settings.py):

# Було (неявно):
# AUTH_USER_MODEL = 'auth.User'

# Стало:
AUTH_USER_MODEL = 'my_app.User'

Тепер вся система авторизації знає: треба дивитися на вашу таблицю.


4. 🛠 Практична частина

Час забруднити руки! Ось ваші завдання.

Завдання 1. Фундамент Створіть новий проєкт. Ще до першої міграції (migrate) створіть модель User, яка наслідує AbstractUser. Додайте в settings.py вказівку на вашу модель.

Завдання 2. Особисті дані Додайте до вашого користувача поля: * date_of_birth (дата народження) * avatar (картинка/ImageField) Зробіть міграції.

Завдання 3. Бізнес-логіка (Метод) Напишіть всередині класу User метод is_adult(self), який повертає True, якщо користувачу більше 18 років, і False, якщо менше. (Підказка: вам знадобиться модуль datetime).

Завдання 4. Виправлення помилки (Кейс) Ви спробували зайти в адмінку, але вона "ламається" або виглядає дивно при створенні юзера. Діагноз: Стандартна адмінка "заточена" під стандартного юзера. Рішення: Вам треба зареєструвати вашу модель в admin.py, використовуючи UserAdmin. Знайдіть, як це зробити.

Завдання 5. "А що, якщо..." А що, якщо ми хочемо, щоб логіном був email, а не username? Як змінити це налаштування у вашій моделі? (Гугліть: USERNAME_FIELD).


5. 💡 Мислення як у розробника

Як відрізнити новачка від профі в цій темі?

⛔️ Помилка новачка: Починає проєкт, створює базу даних, пише код тиждень... А потім згадує: "Ой, мені треба додати телефон до юзера". І починає створювати окрему модель UserProfile, зв'язувати її через OneToOneField... Це працює, але це зайві запити до бази даних (JOIN) і зайвий код.

🧠 Думка Профі: "Я не знаю, яким буде цей проєкт через рік. Але я знаю, що вимоги зміняться. Тому я витрачу 5 хвилин зараз на створення Custom User, щоб зекономити 50 годин рефакторингу потім".

Порада з практики: Ніколи не посилайтеся на модель User напряму в коді (наприклад, у зовнішніх ключах ForeignKey). Замість: user = models.ForeignKey(User, ...) ❌ Пишіть: user = models.ForeignKey(settings.AUTH_USER_MODEL, ...)

Чому? Бо якщо ви колись зміните назву моделі користувача, вам доведеться переписувати весь проєкт. А з другим варіантом — змінити лише один рядок у налаштуваннях. Це і є гнучкість.


6. 🧩 Підсумок

Отже, що ми сьогодні зробили? 1. Ми відмовилися від "стандартного паспорта" і створили свій власний. 2. Зрозуміли, що робити це треба на старті. 3. Навчилися додавати поля та методи до головної сутності системи.

Тепер ви вмієте: Створювати фундамент для будь-якої системи реєстрації, будь то інтернет-магазин, соцмережа чи банківський додаток. Ви контролюєте дані про користувача.

🚀 Що далі? Тепер, коли у нас є крутий користувач, виникає питання: "А кому що можна робити?". Чому адміністратор може видаляти пости, а звичайний юзер — ні? Наступного разу ми поговоримо про Permissions (Дозволи) та Groups. Це буде ваша система безпеки.

А поки що — спробуйте реалізувати свій клас User. Хай щастить!


(Це був CS50... українською версією. Побачимось!)