Django - Tutorial 052. Redefining a User Model

Python, QuerySet, django, Model

Content

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

    def initials(self):
        return get_initials(self)

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.
- company blog
Support the author 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

Благодарю!

  • #
  • May 4, 2020, 4:56 a.m.

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

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

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

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

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

Comments

Only authorized users can post comments.
Please, Log in or Sign up
How to become an author?

Contribute to the evolution of the EVILEG community.

Learn how to become a site author.

Learn it
Donate

Good day, Dear Users!!!

I am Evgenii Legotckoi, developer of EVILEG. And it is my hobby project, which helps to learn programming another programmers and developers

If the site helped you, and you want also support the development of the site, than you can donate by following ways

PayPalYandex.Money
Timeweb

Let me recommend you the excellent hosting on which EVILEG is located.

For many years, Timeweb has been proving his stability.

For projects on Django I recommend VDS hosting

View Hosting Timeweb
June 5, 2020, 11:20 p.m.
Aleksej

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

  • Result:60points,
  • Rating points-1
June 5, 2020, 11:15 p.m.
Aleksej

C++ - Test 001. The first program and data types

  • Result:53points,
  • Rating points-4
V
June 5, 2020, 4:47 p.m.
Vladzo

C++ - Test 005. Structures and Classes

  • Result:83points,
  • Rating points4
Last comments
June 5, 2020, 10:52 a.m.
progammist

Распознавание изображений на Python с помощью TensorFlow и Keras

Огромное спасибо за метериал, по-больше бы подобных статей (с подробным описанием работы и примерами применения) на тему современных технологий. Вопрос поразмышлять. На текущий момент реал…
June 5, 2020, 1:39 a.m.
Evgenij Legotskoj

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

По-моему, смысла в этом нет особого. Если делегат будет игнорировать настройки таблицы, то это приведёт ещё к большему непониманию, что вообще происходит, для программиста, который после вас буд…
June 5, 2020, 1:34 a.m.
IscanderChe

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

Сижу, размышляю: можно ли переписать делегата так, чтобы независимо от настроек строк выделялись строки?
June 5, 2020, 1:31 a.m.
Evgenij Legotskoj

Qt/C++ - Tutorial 091. How to write a custom delegate controlling the highlighting of a row in a table

Понятно. Я не обратил внимания на то, что там было в старом коде по настройкам строк :)
Now discuss on the forum
s
June 6, 2020, 1:54 a.m.
shuric

Qt/C++ Определение положения курсора над действие(кнопкой) в QToolBar

Доброго дня. Возник вопрос - как можно определить что курсор находится над определенным действием(кнопкой) в qtoolbar ? mainwindow.cpp MainWindow::MainWi…
s
June 6, 2020, 12:45 a.m.
shuric

Qt/C++ особенности QProxyStyle

Да, Вы правы. Код был скопирован с сайта (уже не помню с какого), но решил пойти по пути более легком. Пришлось переписать - кому интересно: использовал stackedWidget для пе…
June 5, 2020, 11:08 p.m.
Aleksej

Посоветуйте новичку (базы данных и Qt, что учить)

Блин, а я недавно купил Шлее Qt 5.10 :( С детства хотел стать программистом, баловался Паскалем, писал простенькие программки на Delphi, создавал движок на php, изучал C (забросил и перешел на п…
June 5, 2020, 1:09 p.m.
IscanderChe

QPlainTextEdit настройка цвета фона

Вечер добрый. Пытаюсь настроить цвет фона QPlainTextEdit следующим образом: CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent){ ... QPalette::ColorRole role = bac…
June 5, 2020, 6:13 a.m.
IscanderChe

Фильтр для QtableView sql

Добрый день. Для такой фильтрации необходимо использовать QSortFilterProxyModel. В оффдоках есть хороший пример.
About
Services
© EVILEG 2015-2020
Recommend hosting TIMEWEB