Евгений Легоцкой26 апреля 2020 г. 15:08

Django - Урок 052. Переопределение модели пользователя

Содержание

Есть разные варианты работы с пользовательской моделью для создания профиля пользователя и добавления некоторой специфичной инфоромации, например, фото в профиле. Одним из способов является добавление модели профиля с OneToOneField полем для пользователя. Данный вариант является более просты, чем прокси модели или переопределение модели пользователя. Но лично для меня переопределение модели пользователя оказалось более эффективным в плане организации кода и написании различных методов, которые позволяет извлекать нужную информацию из объекта пользователя в шаблонах не прибегая к написанию шаблонных тегов.

Поэтому давайте рассматрим именно вариант переопределения модели пользователя в проекте на Django

Введение

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

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

Переопределение модели пользователя

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

В своём приложении evileg_auth я сделал это таким образом

# -*- coding: utf-8 -*-

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    pass

Далее вам необходимо указать эту модель в качестве новой модели пользователя в файле настроек settings.py

AUTH_USER_MODEL = 'evileg_auth.User'

Это необходимо для того, чтобы третье сторонние приложение начали использовать вашу модель пользователя вместо стандартной.

После чего можете создать миграции и мигрировать проект

python manage.py makemigrations
python manage.py migrate

Также не забудьте зарегистрировать свою модель в административной панели

# -*- coding: utf-8 -*-

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin

from .models import User

admin.site.register(User, UserAdmin)

Примечания

Если вы внедряете переопределённую модель пользователя в уже существующий проект, то рекомендую выполнить следующие действия, чтобы переопределённая модель использовалась везде в вашем проекте.

settings.AUTH_USER_MODEL

Во всех файлах models.py используйте вместо стандартной модели переменную settings.AUTH_USER_MODEL из настроек

# -*- coding: utf-8 -*-

from django.conf import settings
from django.db import models


class SomeModel(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='User')

get_user_model()

Везде в коде, где предполагается, что инстанс Django уже запущен, используйте динамическое получение класса модели пользователя через get_user_model()

Например, у меня есть такой mixin

class EInUserProfileMixin:
    user_profile = None

    def dispatch(self, request, *args, **kwargs):
        self.user_profile = get_object_or_404(get_user_model(), username=kwargs['user'], is_active=True)
        return super().dispatch(request, *args, **kwargs)

Третьестороннее приложение

Если вы пишите третьестороннее приложение, то рекомендации из раздела примечания для вас должны быть обязательными, поскольку в противном случае ваше третьестороннее приложения будет бесполезным для тех разработчиков, которые переопределяют пользовательские модели в своих проектах на Django

Преимущества переопределения пользовательской модели

Переопределение пользовательской модели имеет, на мой взгляд, большие преимущества по сравнению с использованием OneToOneField, поскольку позволяет без костылей переопределить менеджер объектов, а также добавить ряд методов, которые могут быть полезны в вашем проекте. А также эти методы можно будет вызывать в шаблонах без написания шаблонных тегов.

Вот например часть пользовательской модели в моём проекте

class User(AbstractUser):

    last_online = models.DateTimeField(blank=True, null=True)

    objects = UserManager()

    class Meta:
        ordering = ['username']

    def get_absolute_url(self):
        return reverse('users:profile', kwargs={'user': self.username})

    def initials(self):
        return get_initials(self)

Как минимум мне всегда не хватало использования стандартного метода get_absolute_url для профиля пользователя на сайте.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
- блог компании
Поддержать автора Donate

Полезный урок, весьма лучше, чем создать профиль. А как всё это объединить в админке? admin.site.register(User, UserAdmin) - UserAdmin убрал мое созданное поле для абстрактного поля.

Я немного не понял, что именно вы хотите объединить? Вы хотите, чтобы группы и пользователи были в одном groupbox'e?
Или хотите видеть абстрактное поле? Если абстрактное поле, то наследуйтесь от UserAdmin и переопределите переменные fields и т.д., как если бы наследовались от ModelAdmin

Я уже нашел в вашем другом уроке как добавить поле аватар к пользователям. Именно то что вы написали) Спасяб:3
Да ещё бы хотелось чтоб группы и пользователи были в одной группе.

Да ещё бы хотелось чтоб группы и пользователи были в одной группе.

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

Думаю, что это может выглядеть так

class ProxyGroups(Groups):
    class Meta:
        proxy = True    
        # Если определить ProxyGroup внутри my_auth/models.py,
        # то его app_label будет установлен как 'my_auth' автоматически.
        # Или можно переопределить его так           
        # app_label = 'my_auth'

        # также можно установить некоторые параметры из существующего Group
        # verbose_name = Groups._meta.verbose_name
        # verbose_name_plural = Groups._meta.verbose_name_plural


# in admin.py
admin.site.register(ProxyGroups)

Суть в том, что проксируем стандартную модель Groups в другое приложение, чтобы они отображались в одном app

Благодарю!

  • #
  • 4 мая 2020 г. 5:56

Подскажите, эта серия уроков для django 2.0?

Я ещё не переходил на Django 3, поэтому на данный момент все примеры пишутся с использованием Django 2, наиболее старые с использованием Django 1.

Но в принципе, большая часть из статей должна работать и с Django 3. Хотя и не все.

Понял, большое спасибо! Буду ждать перехода на 3 версию :)

Я тоже его жду. Вернее жду, когда все разработчики третьесторонних библиотек добавят поддержку третьей версии.

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Как стать автором?

Внесите вклад в развитие сообщества EVILEG.

Узнайте, как стать автором сайта.

Изучить
Donate

Добрый день, Дорогие Пользователи !!!

Я Евгений Легоцкой, разработчик EVILEG. И это мой хобби-проект, который помогает учиться программированию другим программистам и разработчикам

Если сайт помог вам, и вы хотите также поддержать развитие сайта, то вы можете сделать пожертвование следующими способами

PayPalYandex.Money
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
R

C++ - Тест 002. Константы

  • Результат:75баллов,
  • Очки рейтинга2
R

C++ - Тест 001. Первая программа и типы данных

  • Результат:73баллов,
  • Очки рейтинга1
MS

C++ - Тест 005. Структуры и Классы

  • Результат:75баллов,
  • Очки рейтинга2
Последние комментарии
V

Django - Урок 027. Добавление Google reCAPTCHA

Спасибо. Только использую декоратор не в urls.py а перед views
R

Qt WinAPI - Урок 001. Как собрать все DLL, используемые в Qt-проекте?

Вы меня не совсем правильно поняли, но все равно спасибо, принял все к сведению. Все сделал как вы сказали, все отлично работает, еще раз огромнейшее спасибо) Разве что только что были опять про…

Qt WinAPI - Урок 001. Как собрать все DLL, используемые в Qt-проекте?

Стоило перед использованием что ли инструкцию прочитать https://www.cyberforum.ru/blogs/131347/blog2457.html "После сборки при запуске требовались dll," Ясное дело стоило задепло…
R
R

Qt WinAPI - Урок 001. Как собрать все DLL, используемые в Qt-проекте?

Да, собралось. После сборки при запуске требовались dll, перекинул всю папки bin, plugins(не знаю как можно было сделать более умно). Как я понял в первой строке путь к екзешнику вставляю, втор…
Сейчас обсуждают на форуме
_
  • _focus
  • 5 июля 2020 г. 1:50

Не работают слоты/сигналы

Помогите разобраться. MainWindow::on_push_autorisation_clicked() - при нажатии на кнопку отправляется сигнал. В слоте выводим текст и отправляем сигнал дальше. Если не отправлять сигна…

Как в Qt в qmenu добавить scrollarea

Вот это наследованный класс меню. Но посути это обычное меню. #pragma once#include <QtWidgets>class TransMenu : public QMenu { Q_OBJECTpublic: TransMenu(QWidget* parent = …

Qt C++ и Python

Красиво/некрасиво - это скорее моё личное отношение. Если есть возможность ограничить количество интсрументов, то лучше ограничить. Но не зацикливайтесь на этом. Если у вас есть скрипты Py…

Qt + OpenGL glDeleteVertexArrays

Я не уверен, поскольку с OpenGL очень мало работал. Но может быть OpenGL контекст виджета нужно переинициализовывать. И ещё виджет стоит удалять через метод deleteLater() а не п…

QWebEngineView не запускается если к ПК подключено несколько мониторов

Ну я имел ввиду посмотреть на другом ПК с другой графикой и парой мониторов. Как моей программе назначить использовать определенный граф. адаптер? Вот тут понятия не имею.
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB