Це чудовий виклик! Давайте створимо цей урок. Я використаю контекст Django (Python), оскільки саме там термін "Custom User Model" є найбільш значущим, а проблеми, пов'язані з ним — класикою веб-розробки. Але логіка буде зрозуміла навіть тим, хто працює з іншими фреймворками.
Ось ваш урок у стилі CS50.
🎓 Урок: Робота з користувацькою моделлю (Custom User Model)
👋 Усім привіт! Я радий вас бачити.
Сьогодні ми поговоримо про дещо фундаментальне. Про те, що є серцем майже будь-якого сучасного веб-застосунку. Ми говоримо про Користувача (User).
Але не просто про якогось абстрактного юзера, а про те, як взяти контроль над ним у свої руки.
1. 🔥 Вступ: Чому стандартного паспорта замало?
Уявіть, що ви будуєте новий житловий комплекс. У вас є стандартна форма реєстрації мешканців, яку вам видала держава (читай: фреймворк). У цій формі є поля: * Ім'я * Прізвище * Пароль (ключ від дверей)
Це чудово працює, якщо ви будуєте гуртожиток. Але що, як ви будуєте елітний клуб? Вам потрібно знати: * Чи є у мешканця собака? (щоб пустити на майданчик) * День народження? (щоб надіслати листівку) * Номер телефону? (для екстреного зв'язку) * Чи є він VIP-клієнтом?
Стандартна форма ("User", який йде в коробці з інструментом) не має цих полів.
❓ Питання до вас: Що робити? Створювати окрему таблицю в Excel під назвою "Додаткова інфа" і намагатися склеїти її з основною? Чи, можливо, одразу переписати бланк реєстрації під свої потреби, поки ми ще не залили фундамент?
Чому без цього не обійтись: У 99% реальних проєктів стандартного користувача (username + password) недостатньо. Якщо ви не створите власну модель користувача на самому початку проєкту, то пізніше, коли у вас вже буде база даних із тисячами людей, змінити це буде так само боляче, як замінити фундамент у вже збудованому хмарочосі.
Тож сьогодні ми навчимося робити це правильно. Одразу.
2. 🧠 Теоретична база: Що там "під капотом"?
Давайте заглянемо всередину.
У більшості фреймворків (наприклад, Django) вже є готова таблиця в базі даних, яка називається auth_user. Розробники фреймворку написали її за вас. Це зручно.
Але Custom User Model (Користувацька модель) — це коли ми кажемо фреймворку:
"Слухай, дякую за твою таблицю, але я хочу використовувати СВОЮ. У ній будуть ті самі поля, що й у тебе, ПЛЮС мої власні".
Два шляхи (інтуїтивне розуміння):
- Шлях "Наслідування" (AbstractUser): Ви берете готовий шаблон користувача і просто дописуєте туди нові поля (телефон, аватарка). Це як взяти типовий проєкт будинку і додати до нього гараж.
- Використовуємо у 90% випадків.
- Шлях "З нуля" (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... українською версією. Побачимось!)