Evgenii Legotckoi
Evgenii LegotckoiApril 26, 2020, 3:08 p.m.

Django - Tutorial 052. Redefining a User Model

There are various options for working with a user model for creating a user profile and adding some specific information, for example, a profile photo. One way is to add a profile model with the OneToOneField field for the user. This option is simpler than a proxy model or overriding a user model. But for me personally, redefinition of the user model turned out to be more effective in terms of organizing code and writing various methods that allow you to extract the necessary information from the user object in templates without resorting to writing template tags.

Therefore, let's consider exactly the option of redefining the user model in a project in Django


Introduction

As an introduction, I’ll draw your attention to the fact that redefining a user model is best done at the very beginning of the project, otherwise there may be problems with migrations that need to be fixed manually.

I myself did overriding the user model already when the site existed for more than two years. However, my redefinition process went relatively smoothly, at least I don’t remember that there were any problems with the fact that I redefined the user model.

User Model Override

In order to correctly redefine the user model, you need to import the abstract user model AbstractUser and inherit from it in the application where you will have the model.

In my application evileg_auth I did it this way

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

from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    pass

Next, you need to specify this model as the new user model in the settings file settings.py

AUTH_USER_MODEL = 'evileg_auth.User'

This is necessary so that a third-party application starts using your user model instead of the standard one.

Then you can create migrations and migrate the project

python manage.py makemigrations
python manage.py migrate

Also do not forget to register your model in the admin panel

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

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

from .models import User

admin.site.register(User, UserAdmin)

Notes

If you are introducing an overridden user model into an existing project, I recommend that you follow these steps so that the overridden model is used everywhere in your project.

settings.AUTH_USER_MODEL

In all models.py files, use the settings.AUTH_USER_MODEL variable from the settings instead of the standard 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()

Everywhere in the code where it is assumed that the Django instance is already running, use the dynamic get of the user model class via get_user_model()

For example, I have such a 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)

Third Party Application

If you are writing a third-party application, then the recommendations from the notes section should be mandatory for you, because otherwise your third-party application will be useless for those developers who redefine custom models in their projects on Django

Benefits of Overriding a Custom Model

Redefining the user model has, in my opinion, great advantages compared to using OneToOneField, since it allows you to redefine the object manager without crutches, as well as add a number of methods that can be useful in your project. And also these methods can be called in templates without writing template tags.

Here is an example of a part of a user model in my project

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})

At a minimum, I always lacked the use of the standard method get_absolute_url for the user profile on the site.

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

Владислав Меленчук
  • April 27, 2020, 7:43 a.m.

Полезный урок, весьма лучше, чем создать профиль. А как всё это объединить в админке? 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

Благодарю!

Z M
  • May 4, 2020, 5:56 a.m.

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

Evgenii Legotckoi
  • May 4, 2020, 5:59 a.m.
  • (edited)

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

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

Z M
  • May 4, 2020, 6:02 a.m.

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

Evgenii Legotckoi
  • May 4, 2020, 6:04 a.m.

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

t
  • Jan. 23, 2021, 8:28 a.m.

Добрый день, Я вот написал в admin.py
admin.site.register(User, UserAdmin)
Но у меня не появилось новые поля в админке?

Evgenii Legotckoi
  • Jan. 31, 2021, 4:30 p.m.

Если у вашего пользователя нет прав но чтение или изменение модели пользователя, то вы можете и не увидеть эту модель в админке. В этом случае лучше под суперпользователем проверять всё.

t
  • Feb. 23, 2021, 7:11 a.m.

А как дать ему эти права?

t
  • Feb. 24, 2021, 2:56 a.m.

В данном случае я заходил под superuser но все равно не появлялись эти поля

N
  • April 19, 2022, 3:22 a.m.

def initials(self):
return get_initials(self)

В последнем листинге что такое get_initials(self), пайчарм подчеркивает и предлагает создать функцию get_initials

Evgenii Legotckoi
  • April 19, 2022, 3:58 a.m.

Лишний кусок кода (Метод для получения инициалов), удалите его.

Comments

Only authorized users can post comments.
Please, Log in or Sign up
AD

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:80points,
  • Rating points4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:20points,
  • Rating points-10
Last comments
ИМ
Игорь МаксимовNov. 22, 2024, 10:51 p.m.
Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiNov. 1, 2024, 12:37 a.m.
Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEOct. 19, 2024, 6:19 p.m.
Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовOct. 5, 2024, 5:51 p.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 9:02 p.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Now discuss on the forum
Evgenii Legotckoi
Evgenii LegotckoiJune 25, 2024, 1:11 a.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Nov. 15, 2024, 5:04 p.m.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectJune 4, 2022, 1:49 p.m.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimOct. 25, 2024, 7:10 p.m.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Follow us in social networks