Django расширение модели user: Django расширение модели User
Содержание
Django расширение модели User
23 Янв 2021 ,
1373
Если вы создаете новый проект на Django , то я рекомендую использовать пользовательскую модель User , которая расширяется от подкласса AbstractBaseUser. Вы конечно , можете этого не делать и использовать другие стратегии , такие как:
Но по моему личному мнению расширение от подкласса AbstractBaseUser является самым гибким способом, хоть и вначале требует определенных усилий для его реализации.
Вначале я вкратце расскажу о других стратегиях расширения модели User. Об их достоинствах и недостатках. А потом мы реализуем создание пользовательской модели с помощью расширения от подкласса AbstractBaseUser
Использование прокси-модели
Эта стратегия используется в том случае , когда нам не нужны новые поля для модели User или переопределения существующих полей, но нужны поведенческие изменения , такие как переопределение сортировки по умолчанию, добавление новых методов для работы с моделью ,использование пользовательских менеджеров.
class CustomUser(User):
objects = PersonManager()
class Meta:
proxy = True
ordering = ('first_name', )
Тут мы создаем прокси-модель Person , которая наследуется от User.Внутри Meta мы указываем proxy=True , чтобы указать , что это модель является прокси. И для этой модели в базе данных не создается таблица.
Достоинством этой стратегии является простота реализации.И эту стратегию вы можете использовать не только при создании проекта , но на любом этапе жизненнего цикла вашего проекта.
Недостатком — ограниченность, так как мы не можем создавать новые поля или переопределять существующие поля.
Использование связи один-к-одному с пользовательской моделью
Если нам нужно хранить дополнительную информацию о существующей модели пользователя и которая не связана с аутентификацией , то мы можем создать новую модель , которая будет связана с существующим моделем User c помощью связи один-к-одному.
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.TextField(max_length=500, blank=True)
bith_date = models.TextField(max_length=500, blank=True)
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Достоинством данной стратегии является то , что мы можем создать новые поля и это можно сделать не только при создании проекта , но в любой момент времени когда вам это понадобится.
Недостатком данной стратегии является то , что у нас будет еще одна таблица с полями для пользователя и создаются лишние запросы при обращении к связанным данным. Это можно в определенной мере решить с использованием selected_related
Расширение от подкласса
AbstractUser
Этот способ в отличие от предыдущих , нужно реализовывать вначале создания проекта перед применением миграций.
Этот метод используется в том случае если вас устраивает аутентификация в том виде , которая предоставляется стандартно , но вам нужно добавить новые данные , но в отличие от прокси-модели не создаете новый класс или создание новой модели с таблицей , как при использовании стратегии использование связи один-к-одному с пользовательской моделью.
Класс django.contrib.auth.models.AbstractUser обеспечивает полную реализацию пользователя по умолчанию как абстрактную модель
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
birth_date = models.DateField(null=True, blank=True)
AUTH_USER_MODEL = 'users.User'
Расширение от подкласса
AbstractBaseUser
Ну и в конце я создам пользовательскую модель путем расширения от класса AbstractBaseUser. Этот способ считается сложным , а некоторые советуют его применять в крайнем случае, но по мне для сложных проектов этот способ является самым предпочитаемым. Но это дело вкуса.
Часто в моих проектах в качестве логина используется либо email или номер телефона. А поле username нам вообще не нужен. Так что мы при создании модели , который наследуются от AbstractBaseUser , можем указать поле , который используется в качестве логина. Хотя , я видел статью где это можно сделать и при расширении от класса AbstractUser.
Ну довольно теории. Создадим виртуальное окружение , установим Django и создадим новый проект.
Создадим новое приложение users и в файле models.py создадим модель User , который будет наследоваться от AbstractBaseUser и от миксина PermissionsMixin
import os
import datetime
import os.path
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.core.validators import RegexValidator
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser, PermissionsMixin
)
class UserManager(BaseUserManager):
def create_user(self, email, password=None,**kwargs):
if not email:
raise ValueError('Users must have an Email')
user = self.model(
email=email,**kwargs)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password):
"""
Creates and saves a superuser with the given email and password.
"""
user = self.create_user(
email,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser,PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField('Фамилия', max_length=255, blank=True, null=True)
last_name = models.CharField('Имя', max_length=255, blank=True, null=True)
avatar = models.ImageField(null=True, blank=True, upload_to='avatars')
date_of_birth = models.DateField(verbose_name="Дата рождения", null=True, blank=True)
last_time_visit = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
class Meta:
verbose_name = 'Пользователь'
verbose_name_plural = 'Пользователи'
Создайте миграции для users. Важно , это вы должны сделать до применения первоначальных миграций
python manage.py makemigrations
Применяем все миграции проекта
python manage.py migrate
Заключение
Для простых проектов вы можете использовать встроенную модель без расширения, так как он из коробки работает прекрасно и выполняет базовые вещи. Для простых сайтов , где не нужна особо работа с пользователями , то применятся вариант из коробки. Для этого блога это вполне хватает ))
Но если вы разрабатываете сложные проекты , то я рекомендую расширять пользовательскую модель. Вначале это сложно и требует некоторых усилий , но в дальнейшем это окупится.
Please enable JavaScript to view the comments powered by Disqus.
comments powered by
Расширение модели User · Django в примерах
Расширение модели User
При работе с учетными записями пользователей вы узнаете, что модель User механизма аутентификации с помощью Джанго подходит для распространенных случаев. Однако модель User поставляется с довольно базовыми возможностями. Пользователь может расширить модель User, включив в нее дополнительные данные. Лучшим способом для этого является создание модели профиля, которая содержит все дополнительные поля и связь «один к одному» с моделью User.
Откройте файл models.py приложения account и внесите в него следующий код:
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
date_of_birth = models.DateField(blank=True, null=True)
photo = models.ImageField(upload_to='users/%Y/%m/%d', blank=True)
def __str__(self):
return 'Profile for user {}'.format(self.user.username)
In order to keep your code generic, use the get_user_model() method to retrieve the user model and the AUTH_USER_MODEL setting to refer to it when defining model’s relations to the user model, instead of referring to the auth User model directly.
Связь «один к одному» позволяет связывать профили с пользователями. Поле photo является полем ImageField . Вам потребуется установить один из пакетов Python для управления изображениями. Установите Pillow, запустив в терминале следующую команду:
pip install Pillow==2.9.0
Для обслуживания файлов мультимедиа, загруженных пользователями с сервероа разработки, добавьте следующие параметры в файл settings.py проекта:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL — это базовый URL-адрес для обслуживания файлов мультимедиа, отправляемых пользователями, а MEDIA_ROOT — локальный путь, в котором они находятся. Мы динамически строим путь относительно нашего пути проекта, чтобы сделать код более универсальным.
Отредактируйте основной файл urls.py проекта bookmarks и добавьте в него следующий код:
from django.account/', include('account.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Таким образом, сервер разработки Джанго будет отвечать за службу мультимедийных файлов во время разработки.
Вспомогательная функция static() подходит для разработки, но не для использования в продакшн версии.Никогда не обслуживайте статические файлы с Джанго в продакшн версии.
Откройте оболочку и выполните следующую команду, чтобы создать миграцию базы данных для новой модели:
python manage.py makemigrations
Вы увидите следующее:
Migrations for 'account':
0001_initial.py:
- Create model Profile
Затем синхронизируйте базу данных следующей командой:
python manage.py migrate
Вы увидите следующее:
Applying account.0001_initial... OK
Измените файл admin.py приложения account и зарегистрируйте модель Profile на сайте администрирования:
from django.contrib import admin
from .models import Profile
class ProfileAdmin(admin.ModelAdmin):
list_display = ['user', 'date_of_birth', 'photo']
admin.site.register(Profile, ProfileAdmin)
Запустите сервер разработки снова с помощью команды python manage.py runserver
. Теперь вы можете видеть модель Profile в административной части сайта вашего проекта:
Теперь мы позволим пользователям редактировать свой профиль на веб-сайте. Добавьте следующие модели формы в файл forms.py приложения account:
from .models import Profile
class UserEditForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class ProfileEditForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('date_of_birth', 'photo')
Немного о коде выше:
- UserEditForm : Позволит пользователям изменять свое имя, фамилию и электронную почту, хранящиеся во встроенной пользовательской модели.
- ProfileEditForm : Позволит пользователям редактировать дополнительные данные, сохраняемые в пользовательской модели Profile. Пользователи смогут изменить дату рождения и отправить фотографию для своего профиля.
Отредактируйте файл views.py приложения account и сделайте импорт модели Profile:
from .models import Profile
И добавьте следующие строки в представление register под new_user.save():
profile = Profile.objects.create(user=new_user)
Когда пользователи регистрируются на нашем сайте, мы создаем пустой профиль, связанный с ними. Необходимо создать объект Profile вручную с помощью административной части сайта для созданных ранее пользователей.
Теперь мы позволим пользователям редактировать их профиль. Добавьте следующий код в тот же файл:
from .forms import LoginForm, UserRegistrationForm, UserEditForm, ProfileEditForm
@login_required
def edit(request):
if request.method == 'POST':
user_form = UserEditForm(instance=request.user, data=request.POST)
profile_form = ProfileEditForm(instance=request.user.profile, data=request.POST, files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form = UserEditForm(instance=request.user)
profile_form = ProfileEditForm(instance=request.user.profile)
return render(request,
'account/edit.html',
{'user_form': user_form,
'profile_form': profile_form})
Мы используем декоратор login_required, так как пользователи должны авторизоваться для редактирования своего профиля. В этом случае используются две модели форм: UserEditForm для хранения данных встроенной модели User и ProfileEditForm для хранения дополнительных данных профиля. Чтобы проверить представленные данные, мы проверяем, что метод is_valid() обеих форм возвращает значение true.edit/$’, views.edit, name=’edit’),
Наконец, создайте шаблон для этого представления в templates/account/ и назовите его edit.html. Добавьте в него следующий код:
{% extends "base.html" %}
{% block title %}Edit your account{% endblock %}
{% block content %}
<h2>Edit your account</h2>
<p>You can edit your account using the following form:</p>
<form action="." method="post" enctype="multipart/form-data">
{{ user_form.as_p }}
{{ profile_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Save changes"></p>
</form>
{% endblock %}
We include enctype=»multipart/form-data» in our form to enable file uploads. We use one HTML form to submit both the user_form and the profile_form forms.
Зарегистрируйте нового пользователя и пройдите по адресу http://127.0.0.1:8000/account/edit/ . Вы увидите следующую страницу:
Теперь можно также отредактировать страницу панели мониторинга и включить ссылки для редактирования страниц профиля и смены пароля. Откройте шаблон account/dashboard.html и замените эту строку:
<p>Welcome to your dashboard.</p>
…на эту:
<p>Welcome to your dashboard. You can <a href="{% url "edit" %}">edit your profile</a> or <a href="{% url "password_change" %}">change your password</a>.</p>
Теперь пользователи могут получить доступ к форме для редактирования профиля в панели управления.
Пользовательская модель User | Советы для Джанго
Каждый новый проект Django должен использовать пользовательскую модель User. Официальная документация Django гласит, что это «настоятельно рекомендуется», но я сделаю еще один шаг и без колебаний скажу: вы просто с ума сошли, если не использовали пользовательскую модель раньше.
Зачем? Потому что вам придется внести изменения в пользователя в какой-то момент в жизни вашего проекта — добавить поле даты рождения, возраст, что угодно — и если вы не начали с пользовательской модели User до самой первой выполненной вами команды переноса, тогда вы попадете в мир боли.
Однако, если вы используете пользовательскую модель, вы можете легко добавлять и изменять ее.
Можно ли переключиться на пользовательскую модель в середине проекта? Да. Хочешь ли ты это сделать? Лучше не делать.
Вот самый простой способ, чтобы начать каждый новый проект с правильного пути.
Шаг 1. Создание нового проекта
В командной строке перейдите в новый каталог для своих проектов, используйте Pipenv для установки Django, активируйте виртуальную среду и создайте новый проект с именем new_project
. Давайте предположим, что мы хотим использовать папку code
в Desktop
, так пример на Mac.
$ cd ~/Desktop
$ mkdir code && cd code
$ pipenv install django
$ pipenv shell
(code) $ django-admin startproject new_project .
Теперь нам нужно создать приложение пользователя, а затем обновить 4 файла. Готовы?
Шаг 2. Создание приложения пользователя
(code) $ python manage.py startapp users
Теперь давайте расскажем Django о новом приложении и обновим AUTH_USER_MODEL
, чтобы Django знал, что нужно использовать нашу новую модель CustomUser
вместо модели User по умолчанию.
Откройте new_project/settings.py
в текстовом редакторе и внесите следующие два изменения:
# new_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Local
'users.apps.UsersConfig', # новое
]
...
AUTH_USER_MODEL = 'users.CustomUser' # новое
Шаг 3. Модель CustomUser
Мы хотим расширить (или скопировать) существующую модель User
и назвать ее как-то иначе, в нашем случае CustomUser
. Это все, что нам нужно сделать. Просто сделайте копию, и тогда мы сможем настроить ее так, как нам нравится, но при этом использовать все преимущества встроенного User
.
Нам даже не нужно добавлять поле на этом этапе!
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
pass
# add additional fields in here
Шаг 4: Обновление форм
Django использует модель User
— теперь нашу модель CustomUser
, поскольку мы указали ее в AUTH_USER_MODEL
повсюду. Два основных места — это когда создается новый пользователь и когда мы что-то меняем у пользователя. Поэтому мы должны снова расширить встроенные формы для этого и указать их для нашей новой модели CustomUser
.
Создайте новый файл users/forms.py
и заполните его следующим текстом:
# users/forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = CustomUser
fields = ('username', 'email')
Шаг 5: Обновление admin.py
Модель Django User
тесно связана с превосходным встроенным приложением администратора admin
, поэтому мы должны указать Django использовать вместо этого CustomUser
. Вот как:
# users/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm, CustomUserChangeForm
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
form = CustomUserChangeForm
model = CustomUser
list_display = ['email', 'username',]
admin.site.register(CustomUser, CustomUserAdmin)
Всё!!!
И это все. Создайте файл миграции для наших изменений, а затем впервые запустите миграцию, чтобы инициализировать нашу базу данных с помощью CustomUser
вместо User
.
(code) $ python manage.py makemigrations users
(code) $ python manage.py migrate
Поздравляем! Ваш проект Django рассчитан на будущее и вы можете продолжить работу без проблем.
Перевод статьи https://wsvincent.com/django-tips-custom-user-model/
Поделитесь с другими:
Расширение модели пользователя с помощью пользовательских полей в Django
Как лучше всего расширить модель пользователя (в комплекте с приложением аутентификации Django) с помощью пользовательских полей? Я также, возможно, хотел бы использовать email в качестве имени пользователя (для целей аутентификации).
Я уже видел несколько способов сделать это, но не могу решить, какой из них лучше.
django
django-models
django-authentication
django-users
Поделиться
Источник
Farinha
04 сентября 2008 в 16:19
12 ответов
269
Наименее болезненный и действительно Django-рекомендуемый способ сделать это-через свойство OneToOneField(User)
.
Если вы хотите сохранить информацию, связанную с
User
, вы можете использовать отношение one-to-one к модели, содержащей поля для получения дополнительной информации. Эта модель one-to-one часто называется моделью профиля, так как она может хранить не связанную с аутентификацией информацию о пользователе сайта.
Тем не менее, расширение django.contrib.auth.models.User
и его замена также работают…
Некоторые виды проектов могут иметь требования к аутентификации, для которых встроенная модель Django
User
не всегда подходит. Например, на некоторых сайтах имеет смысл использовать адрес email в качестве идентификационного маркера вместо имени пользователя.[Эд: следуют два предупреждения и уведомление, в котором упоминается, что это довольно радикально .]
Я бы определенно держался подальше от изменения фактического класса пользователя в вашем исходном дереве Django и/или копирования и изменения модуля auth.
Поделиться
Ryan Duffield
04 сентября 2008 в 17:02
232
Примечание: этот ответ устарел. см.Другие ответы, если вы используете Django 1.7 или более позднюю версию.
Вот как я это делаю.
#in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
#other fields here
def __str__(self):
return "%s's profile" % self.user
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'
Это приведет к созданию профиля пользователя при каждом сохранении пользователя, если он будет создан.
Затем вы можете использовать
user.get_profile().whatever
Вот еще несколько сведений из документов
http://docs.djangoproject.com/en/dev/темы/auth/#storing-additional-information-about-users
Обновление: Обратите внимание, что AUTH_PROFILE_MODULE
устарел с v1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module
Поделиться
Raisins
08 июня 2009 в 16:53
- Django: UserProfile с уникальным внешним ключом в Django Admin
Я расширил модель пользователя Django, используя пользовательский профиль пользователя под названием UserExtension . Он связан с пользователем через уникальную связь ForeignKey, которая позволяет мне редактировать его в admin В встроенной форме! Я использую сигнал для создания нового профиля для…
- Django пользовательские менеджеры для модели пользователя
Как бы я расширил модель пользователя по умолчанию с помощью пользовательских менеджеров? В моем приложении есть много типов пользователей, которые будут определены с помощью встроенной модели групп. Таким образом, пользователь может быть клиентом, сотрудником и т. д. Было бы идеально иметь…
204
Что ж, с 2008 года прошло некоторое время, и пришло время для нового ответа. Начиная с Django 1.5 вы сможете создавать пользовательский класс пользователя. На самом деле, в то время, когда я пишу это, он уже слился с master, так что вы можете попробовать его.
Есть некоторая информация об этом в документах или, если вы хотите копнуть глубже, в этом коммите .
Все, что вам нужно сделать, это добавить AUTH_USER_MODEL
в настройки с путем к пользовательскому классу пользователя, который расширяет либо AbstractBaseUser
(более настраиваемая версия), либо AbstractUser
(более или менее старый класс пользователя, который вы можете расширить).
Для людей, которым лень нажимать, вот пример кода (взят из docs ):
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
u = self.create_user(username,
password=password,
date_of_birth=date_of_birth
)
u.is_admin = True
u.save(using=self._db)
return u
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
@property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Поделиться
Ondrej Slinták
28 сентября 2012 в 22:22
53
Начиная с Django 1.5 вы можете легко расширить модель пользователя и сохранить одну таблицу в базе данных.
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
class UserProfile(AbstractUser):
age = models.PositiveIntegerField(_("age"))
Вы также должны настроить его как текущий класс пользователя в файле настроек
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"
Если вы хотите добавить много предпочтений пользователей, вариант OneToOneField может быть лучшим выбором.
Примечание для людей, разрабатывающих сторонние библиотеки: если вам нужно получить доступ к пользовательскому классу, помните, что люди могут его изменить. Используйте официальный помощник, чтобы получить правильный класс
from django.contrib.auth import get_user_model
User = get_user_model()
Поделиться
Riccardo Galli
20 апреля 2013 в 21:56
Поделиться
Dmitry Mukhin
04 сентября 2008 в 16:35
23
Ниже приведен еще один подход к расширению пользователя.
Я чувствую,что это более ясно,легко, читаемо, чем выше двух подходов.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Использование вышеуказанного подхода:
- вам не нужно использовать
user.get_profile().новый атрибут для доступа к дополнительной информации
, относящейся к пользователю - вы можете просто напрямую получить доступ
к дополнительным новым атрибутам через
user.newattribute
Поделиться
Rama Vadakattu
01 апреля 2009 в 13:01
17
Вы можете просто расширить профиль пользователя, создавая новую запись каждый раз, когда пользователь создается с помощью сигналов Django post save
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User, related_name='profile')
city = models.CharField(max_length=100, null=True)
def __unicode__(self): # __str__
return unicode(self.user_name)
def create_user_profile(sender, instance, created, **kwargs):
if created:
userProfile.objects.create(user_name=instance)
post_save.connect(create_user_profile, sender=User)
Это автоматически создаст экземпляр сотрудника при создании нового пользователя.
Если вы хотите расширить модель пользователя и хотите добавить дополнительную информацию при создании пользователя, вы можете использовать django-betterforms ( http://django-betterforms.readthedocs.io/en/latest/multiform.html ). Это создаст форму добавления пользователя со всеми полями, определенными в модели UserProfile.
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User)
city = models.CharField(max_length=100)
def __unicode__(self): # __str__
return unicode(self.user_name)
from django import forms
from django.forms import ModelForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
from .models import *
class ProfileForm(ModelForm):
class Meta:
model = Employee
exclude = ('user_name',)
class addUserMultiForm(MultiModelForm):
form_classes = {
'user':UserCreationForm,
'profile':ProfileForm,
}
from django.shortcuts import redirect
from .models import *
from .forms import *
from django.views.generic import CreateView
class AddUser(CreateView):
form_class = AddUserMultiForm
template_name = "add-user.html"
success_url = '/your-url-after-user-created'
def form_valid(self, form):
user = form['user'].save()
profile = form['profile'].save(commit=False)
profile.user_name = User.objects.get(username= user.username)
profile.save()
return redirect(self.add-user/$', AddUser.as_view(), name='add-user'),
]
Поделиться
Atul Yadav
25 июня 2016 в 03:09
9
Расширение модели пользователя Django (UserProfile) как профессионал
Я нашел это очень полезным: ссылка
Выписка:
от django.contrib.auth.models пользователя импорта
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department
Поделиться
Massimo Variolo
13 апреля 2016 в 08:09
3
Новое в Django 1.5, теперь вы можете создать свою собственную пользовательскую модель пользователя (что, по-видимому, хорошо в приведенном выше случае). См. раздел «Настройка аутентификации в Django».
Вероятно, самая крутая новая функция в выпуске 1.5.
Поделиться
chhantyal
12 марта 2013 в 10:01
2
Это то, что я делаю, и, на мой взгляд, это самый простой способ сделать это. определите диспетчер объектов для новой настраиваемой модели, а затем определите свою модель.
from django.db import models
from django.contrib.auth.models import PermissionsMixin, AbstractBaseUser, BaseUserManager
class User_manager(BaseUserManager):
def create_user(self, username, email, gender, nickname, password):
email = self.normalize_email(email)
user = self.model(username=username, email=email, gender=gender, nickname=nickname)
user.set_password(password)
user.save(using=self.db)
return user
def create_superuser(self, username, email, gender, password, nickname=None):
user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(PermissionsMixin, AbstractBaseUser):
username = models.CharField(max_length=32, unique=True, )
email = models.EmailField(max_length=32)
gender_choices = [("M", "Male"), ("F", "Female"), ("O", "Others")]
gender = models.CharField(choices=gender_choices, default="M", max_length=1)
nickname = models.CharField(max_length=32, blank=True, null=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
REQUIRED_FIELDS = ["email", "gender"]
USERNAME_FIELD = "username"
objects = User_manager()
def __str__(self):
return self.username
Не забудьте добавить эту строку кода в свой settings.py
:
AUTH_USER_MODEL = 'YourApp.User'
Это то, что я делаю, и это всегда работает.
Поделиться
Milad Khodabandehloo
25 июля 2018 в 05:00
1
Простой и эффективный подход-это
models.py
from django.contrib.auth.models import User
class CustomUser(User):
profile_pic = models.ImageField(upload_to='...')
other_field = models.CharField()
Поделиться
NeerajSahani
22 февраля 2020 в 18:36
Поделиться
David Torrey
18 ноября 2019 в 19:18
Похожие вопросы:
Расширение модели django.contrib.auth.models.User с помощью пользовательских полей в Django
Я использую Django 1.8.2 с python 2.7.3, rest framework и allauth. Я пытаюсь расширить django.contrib.auth.models.User для добавления пользовательских полей, но возвращаемый json пуст, и есть…
добавление пользовательских полей пользователя с помощью 5NF+
Q-ищете примеры / учебник 5NF/или 6NF, pref для пользовательских полей пользователя, подробности ниже Проводя некоторые исследования по добавлению пользовательских полей пользователя, таких как in…
Расширение формы модели пользователя с помощью пользовательских полей
После регистрации я хотел бы запросить у пользователя: Полное имя (хотя я хочу сохранить его как имя и фамилию) Название компании Email Пароль Я прочитал десятки подобных ситуаций на StackOverflow….
Расширение модели пользователя с помощью пользовательских полей в Django
Я пытаюсь расширить пользовательскую модель, чтобы добавить свои собственные пользовательские поля, но постоянно получаю сообщение об ошибке: ‘NoneType’ объект не имеет атрибута ‘_default_manager’…
Расширение пользовательского объекта в Django: наследование модели пользователя или использование UserProfile?
Чтобы расширить пользовательский объект с помощью пользовательских полей, в документах Django рекомендуется использовать UserProfiles . Однако, согласно этому ответу на вопрос об этом примерно год…
Django: UserProfile с уникальным внешним ключом в Django Admin
Я расширил модель пользователя Django, используя пользовательский профиль пользователя под названием UserExtension . Он связан с пользователем через уникальную связь ForeignKey, которая позволяет…
Django пользовательские менеджеры для модели пользователя
Как бы я расширил модель пользователя по умолчанию с помощью пользовательских менеджеров? В моем приложении есть много типов пользователей, которые будут определены с помощью встроенной модели…
В Django расширение формы пользователя для пользовательского пользователя
Я расширил свою пользовательскую модель, как описано в этой публикации SO: Расширение модели пользователя с помощью пользовательских полей в Django Тем не менее, я пытаюсь создать форму создания…
Расширение модели пользователя в django
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance / Когда дело доходит до расширения модели пользователя, в приведенной выше статье перечислены два метода:…
Расширьте модель пользователя Django с помощью пользовательских полей, приемников и бэкенда
Я разрабатываю приложение Django (v1.6) и должен сделать несколько вещей с пользователями: Добавление пользовательских полей, таких как внешний ключ для отдела пользователей Запускает изменения базы…
Расширение модели auth.User, проксированных полей и Django admin
(Правка: я знаю, что в Django есть совершенно отдельная функция под названием «Proxy Models». Эта функция мне не помогает, потому что мне нужно иметь возможность добавлять поля в UserProfile.)
Итак, я запускаю новое приложение Django и создаю модель UserProfile, которая является расширением django.contrib.auth.models.User и неудачными запросами атрибутов обратно к пользователю, следующим образом:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
def __getattr__(self, name, *args):
if name == 'user' or name == '_user_cache':
raise AttributeError(name)
try:
return getattr(self.user, name, *args)
except AttributeError, e:
raise AttributeError(name)
В целом это работает нормально, но ломается, когда я пытаюсь использовать поле User
в UserProfileAdmin.list_display. Проблема заключается в коде проверки администратора здесь:
def validate(cls, model):
"""
Does basic ModelAdmin option validation. Calls custom validation
classmethod in the end if it is provided in cls. The signature of the
custom validation classmethod should be: def validate(cls, model).
"""
# Before we can introspect models, they need to be fully loaded so that
# inter-relations are set up correctly. We force that here.
models.get_apps()
opts = model._meta
validate_base(cls, model)
# list_display
if hasattr(cls, 'list_display'):
check_isseq(cls, 'list_display', cls.list_display)
for idx, field in enumerate(cls.list_display):
if not callable(field):
if not hasattr(cls, field):
if not hasattr(model, field):
try:
opts.get_field(field)
except models.FieldDoesNotExist:
raise ImproperlyConfigured("%s.list_display[%d], %r is not a callable or an attribute of %r or found in the model %r."
% (cls.__name__, idx, field, cls.__name__, model._meta.object_name))
Проблема в том, что в то время как экземпляр UserProfile будет иметь проксированные поля, например email, сам класс UserProfile этого не делает. Предназначалась в Django shell:
>>> hasattr(UserProfile, 'email')
False
>>> hasattr(UserProfile.objects.all()[0], 'email')
True
После некоторого копания, похоже, я хотел бы переопределить django.db.models.options.Options.get_field для UserProfile._meta. Но, похоже, нет никакого нехакового способа сделать это (прямо сейчас у меня есть очень Хак-решение, которое включает в себя обезьянье исправление UserProfile._meta.[get_field, get_field_by_name])…есть предложения? Спасибо.
python
django
django-models
django-admin
proxy-classes
Поделиться
Источник
rfrankel
06 марта 2011 в 01:38
3 ответа
- django admin сортировка списка полей внешнего ключа
Есть ли опция в представлении django admin для упорядочения полей внешнего ключа? т. е. у меня есть внешний ключ к модели School, который отображается в виде выпадающего списка, отсортированного по pk-я бы хотел, чтобы он был отсортирован в алфавитном порядке.
- Как использовать пользовательские поля формы для полей модели в Django admin?
Я хочу, чтобы Django admin использовал пользовательское поле формы для ввода некоторых полей. До сих пор я делал пользовательское поле модели, к которому было привязано поле формы, которое отлично работает, но оно вводит ненужное поле модели, которое не добавляет никакой пользы. Я предполагаю, что…
2
Будь проще. Вот пример модели UserProfile из библиотеки, которую мы используем:
class UserProfile(models.Model):
user = models.OneToOneField(User)
accountcode = models.PositiveIntegerField(null=True, blank=True)
Вот и все. Не беспокойтесь о переопределении __getattr__
. Вместо этого настройте интерфейс администратора:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class UserProfileInline(admin.StackedInline):
model = UserProfile
class StaffAdmin(UserAdmin):
inlines = [UserProfileInline]
# provide further customisations here
admin.site.register(User, StaffAdmin)
Это позволяет вам CRUD объект User
с доступом к UserProfile в качестве встроенного. Теперь вам не нужно прокси-поиск атрибутов из UserProfile в пользовательскую модель. Чтобы получить доступ к UserProfile
из экземпляра User u
, используйте u.get_profile()
Поделиться
Josh Smeaton
06 марта 2011 в 05:45
0
Если вы просто хотите, чтобы поле от пользователя было в list_display в вашем UserProfileAdmin, попробуйте:
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user__email',)
Если вы хотите, чтобы он был частью формы, добавьте его в UserProfileForm в качестве дополнительного поля и проверьте его в форме.
Поделиться
Matthew Schinckel
06 марта 2011 в 05:14
0
Это не прокси-класс, это отношения. Подробнее о прокси-модели s, которые являются подклассом исходной модели, с Meta.proxy = True
Поделиться
Matthew Schinckel
06 марта 2011 в 02:03
Похожие вопросы:
Django admin поиск и редактирование внешних полей
У меня есть вопрос из двух частей, касающийся Django Admin. Во-первых, у меня есть модель Django Classified , которая имеет поле внешнего ключа из другой таблицы Address . При настройке данных у…
Вложенные наборы полей на странице django admin
Пытаюсь понять Django Admin немного лучше, но сталкиваюсь с проблемой при размещении вложенных наборов полей в django admin Я хочу сгруппировать поля моей модели, как показано на рисунке ниже. Я…
расширение модели django admin
Представление по умолчанию для модели на странице django admin показывает список элементов в этом представлении, но дает только одно поле. Как можно показать несколько полей в списке?
django admin сортировка списка полей внешнего ключа
Есть ли опция в представлении django admin для упорядочения полей внешнего ключа? т. е. у меня есть внешний ключ к модели School, который отображается в виде выпадающего списка, отсортированного по…
Как использовать пользовательские поля формы для полей модели в Django admin?
Я хочу, чтобы Django admin использовал пользовательское поле формы для ввода некоторых полей. До сих пор я делал пользовательское поле модели, к которому было привязано поле формы, которое отлично…
django, где ‘auth.User-проходите мимо.
В каком-то проекте я обнаружил, что определение модели приложения выглядит следующим образом: from django.db import models class CustomUser(models.Model): user = models.ForeignKey(‘auth.User’) мой…
Django: ValueError: ошибка поиска модели, на которую ссылается поле account.UserProfile.user: auth.User
Получение этой ошибки при запуске python manage.py migrate : ValueError: не удалось выполнить поиск модели, на которую ссылается поле account.UserProfile.user: auth.User Шаги, которые я сделал: 1….
Описание модели в django-admin
Можно ли поместить описание модели или описание на страницу отображения списка определенной модели в django-admin? Я говорю о чем-то вроде того, когда вы нажимаете ссылку на название модели на…
Отражение/поиск в модели Django не находит интернационализированных (теневых) полей
Я использую CMS, который выполняет отображение моих моделей через API во время выполнения. Это работает прекрасно, за исключением локализованных полей, потому что я использую…
Есть ли виджет django admin, который позволяет администратору сортировать объекты модели по значениям полей?
Я создаю приложение в Django. Я обнаружил, что существует очень простой способ интегрировать виджет в django admin, который позволяет администратору фильтровать объекты модели по значениям полей….
Расширяем модель User в Django – apirobot
Для работы с пользователями, Django предоставляет готовую модель User. Часто, одной этой модели недостаточно. Приходится ее расширять, либо переписывать, если не устраивает стандартная реализация.
Несколько причин, почему может не устраивать стандартная реализация:
- Вам нужно вместо двух полей first_name и last_name, одно поле full_name.
- Не устраивает то, что поле email – необязательно (blank=True).
- Не устраивает то, что USERNAME_FIELD = ‘username’. USERNAME_FIELD указывает на поле, которое является уникальным идентификатором для пользователя. Кроме того, это поле используется на странице с авторизацией. Получается, что по умолчанию, пользователь вводит username и password. Если вам нужна авторизация через email, то USERNAME_FIELD нужно переопределить на ‘email’.
Рекомендую посмотреть исходный код модели User здесь. Так будет проще понять, о чем я говорю.
В этом уроке поговорим о двух методах расширения модели User:
(1) Создание модели User, которая наследуется либо от AbstractUser, либо от AbstractBaseUser.
Класс AbstractUser, по функционалу, является той самой моделью User, которую вы получаете от Django из коробки. Если вас устраивает стандартная реализация, но нужно ее расширить, то наследуйтесь от AbstractUser. Если нет, то наследуйтесь от AbstractBaseUser и переопределяйте поля сами.
(2) Создание двух моделей: User и Profile, которые связаны друг с другом отношением один-к-одному (OneToOneField).
Зачем создавать две модели? Дело в том, что в программировании есть концепция Single Responsibility Principle (Принцип единственной обязанности).
«На каждый объект должна быть возложена одна единственная обязанность»
Single Responsibility Principle
Другими словами, класс и метод должны делать только одну вещь. Не нужно создавать так называемый God Object, который делает все, что только можно. Не нужно создавать метод, в котором реализована и валидация, и сохранение объекта в файл, и отправка сообщения пользователю… Для каждого метода должна существовать только одна причина его изменения. Если в методе вы хотите изменить как происходит валидация, то это одна причина изменения. Если хотите изменить реализацию отправки сообщения пользователю, то это другая причина. Когда причин больше чем одна, это значит, что метод делает слишком много.
Итак, следуя принципу единственной обязанности, мы создаем:
- Модель User, которая отвечает только за аутентификацию и авторизацию пользователя в системе.
- Модель Profile, которая хранит всевозможную информацию о пользователе для отображения на странице.
User, наследуемый от AbstractUser
Это самый простой способ, т.к. класс AbstractUser уже предоставляет все, что нужно.
Cоздаем приложение:
$ django-admin startapp users
Создаем модель:
# users/models.py from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): bio = models.CharField(max_length=160, null=True, blank=True) birthday = models.DateField(null=True, blank=True) def __str__(self): return self.username
Добавляем путь к модели User в настройках проекта, чтобы Django использовал нашу модель вместо стандартной:
# settings.py AUTH_USER_MODEL = 'users.User'
User, наследуемый от AbstractBaseUser
Cоздаем приложение:
$ django-admin startapp users
Создаем модель:
# users/models.py from django.core.mail import send_mail from django.contrib.auth.base_user import AbstractBaseUser from django.contrib.auth.models import PermissionsMixin from django.contrib.auth.validators import UnicodeUsernameValidator from django.db import models from django.utils.translation import ugettext_lazy as _ class User(AbstractBaseUser, PermissionsMixin): username_validator = UnicodeUsernameValidator() username = models.CharField( max_length=150, unique=True, validators=[username_validator], ) email = models.EmailField(unique=True) full_name = models.CharField(max_length=255) bio = models.CharField( max_length=160, null=True, blank=True ) birthday = models.DateField( null=True, blank=True ) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username', 'full_name'] objects = UserManager() def __str__(self): return self.email def get_short_name(self): return self.email def get_full_name(self): return self.full_name def email_user(self, subject, message, from_email=None, **kwargs): send_mail(subject, message, from_email, [self.email], **kwargs)
- USERNAME_FIELD – уникальный идентификатор пользователя. Это поле, вместе с паролем, используется при авторизации.
- REQUIRED_FIELDS – список полей, которые потребуется ввести при создании пользователя через команду createsuperuser. Также этот список нередко используется сторонними библиотеками, при создании формы с регистрацией. Нормальная форма с регистрацией включает в себя: USERNAME_FIELD, REQUIRED_FIELDS и password.
- is_active – активен ли пользователь или нет. Когда пользователь пытается удалить аккаунт, мы присваиваем полю is_active=false. Аккаунт из базы данных не удаляется. Это делается ради сохранения информации об активности пользователя.
- is_staff – имеет ли пользователь доступ к панели администратора или нет.
Создаем свой UserManger и переопределяем методы, которые отвечают за создание пользователя:
# users/models.py from django.contrib.auth.base_user import BaseUserManager class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, username, full_name, password, **extra_fields): """ Create and save a user with the given username, email, full_name, and password. """ if not email: raise ValueError('The given email must be set') if not username: raise ValueError('The given username must be set') if not full_name: raise ValueError('The given full name must be set') email = self.normalize_email(email) username = self.model.normalize_username(username) user = self.model( email=email, username=username, full_name=full_name, **extra_fields ) user.set_password(password) user.save(using=self._db) return user def create_user(self, email, username, full_name, password=None, **extra_fields): extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) return self._create_user( email, username, full_name, password, **extra_fields ) def create_superuser(self, email, username, full_name, password, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self._create_user( email, username, full_name, password, **extra_fields )
Добавляем путь к модели User в настройках проекта, чтобы Django использовал нашу модель вместо стандартной:
# settings.py AUTH_USER_MODEL = 'users.User'
User и Profile со связью один-к-одному
Cоздаем приложение:
$ django-admin startapp profiles
Модель User переопределять не будем. Возьмем ту, что предоставляет Django из коробки. Создадим модель Profile:
# profiles/models.py from django.conf import settings from django.db import models class Profile(models.Model): user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE ) bio = models.CharField( max_length=160, null=True, blank=True ) birthday = models.DateField( null=True, blank=True ) def __str__(self): return self.user.username
Осталось решить две проблемы:
- После создания пользователя, не создается новый Profile, прикрепленный к этому пользователю.
- После вызова метода save у пользователя, не вызывается метод save у прикрепленного к нему профиля. Из-за этого приходится каждый раз вызывать метод save после изменения профиля:
>>> user.username = 'apirobot' >>> user.profile.bio = 'Something about me' >>> user.profile.save() >>> user.save()
Signals to the rescue! Сигналы позволяют определённым отправителям (senders) уведомлять некоторый набор получателей (receivers) о совершении действий. Используем встроенный в Django сигнал post_save, который отсылается после завершения работы метода save:
# profiles/signals.py from django.contrib.auth import get_user_model from django.db.models.signals import post_save from django.dispatch import receiver from .models import Profile User = get_user_model() @receiver(post_save, sender=User) def create_or_update_user_profile(sender, instance, created, **kwargs): if created: instance.profile = Profile.objects.create(user=instance) instance.profile.save()
Не забудьте подключить сигналы в методе ready конфигурационного класса:
# profiles/apps.py from django.apps import AppConfig class ProfilesConfig(AppConfig): name = 'profiles' def ready(self): import profiles.signals
Тестируем профиль через shell:
>>> from django.contrib.auth import get_user_model >>> User = get_user_model() >>> User.objects.create_user(username='apirobot', password='password') <User: apirobot> >>> user = User.objects.first() >>> user.profile <Profile: apirobot> >>> user.profile.bio = 'Something about me' >>> user.save() >>> User.objects.first().profile.bio 'Something about me'
Напоследок хотелось бы сказать, что не стоит забывать про оптимизацию запросов к базе данных. По умолчанию, Django ORM не включает в результат связанные объекты. Поэтому, при каждом обращении к пользователю через профиль, делается новый запрос к базе данных:
# Запрос к базе данных profile = Profile.objects.get(id=1) # Снова запрос к базе данных для получения объекта User user = profile.user
Это может стать проблемой, когда вы получаете список всех профилей и отображаете в html шаблоне данные профиля и связанного с ним пользователя:
# profiles/views.py from django.views import generic from .models import Profile class ProfileListView(generic.ListView): model = Profile
<!-- profiles/templates/profiles/profile_list.html --> {% for profile in profile_list %} {{ profile.user.username }} {# Делает запрос к базе данных для каждого профиля #} {{ profile.bio }} {% endfor %}
Такая проблема решается с помощью метода select_related, который добавляет к результату запроса связанный объект:
# Запрос к базе данных profile = Profile.objects.select_related('user').get(id=1) # Не делает запрос к базе данных, т.к. `profile.user` # был получен в предыдущем запросе user = profile.user
Исправляем представление из предыдущего примера:
# profiles/views.py class ProfileListView(generic.ListView): queryset = Profile.objects.select_related('user')
Заключение
В этом уроке мы поговорили о методах расширения модели User. Если вы не определились с выбором между User + Profile или просто User, то следуйте своему сердцу. После просмотра исходного кода проектов на GitHub, я понял, что каждый делает так, как хочет. В одних проектах всё пихают в модель User, в других используют User + Profile.
Имеет смысл создавать модель Profile, когда в моделе User много кода или когда вы хотите, чтобы модель User отвечала только за аутентификацию и авторизацию пользователя. Если же ваша модель User небольшая и вы не хотите париться по поводу создания сигналов и оптимизации запросов, то Profile вам не нужен.
python — Расширение модели пользователя Django и добавление в список администраторов
Я пытаюсь расширить свою модель пользователя с помощью профиля, а затем добавить новые поля профиля в отображение списка пользователей, чтобы он был доступен для поиска. Все работает до тех пор, пока не добавится в список администратора.
Я продолжаю получать эту ошибку 'User' object has no attribute 'MyProfile'
Models.py
from django.db import models
# Create your models here.
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from userena.models import UserenaBaseProfile
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
dealer_num = models.CharField(blank=True,
max_length=15,
verbose_name="Dealer Number")
Admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from .models import MyProfile
class ProfileInline(admin.StackedInline):
model = MyProfile
can_delete = False
verbose_name_plural = 'Profile'
fk_name = 'user'
fields = ('user', 'dealer_num')
class UserAdmin(UserAdmin):
inlines = (ProfileInline, )
list_display = ('username', 'get_dealer_num')
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(UserAdmin, self).get_inline_instances(request, obj)
def get_dealer_num(self, obj):
return obj.MyProfile.dealer_num
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
0
Chris Wendel
7 Мар 2019 в 23:41
1 ответ
Лучший ответ
Попробуй это:
def get_dealer_num(self, obj):
return MyProfile.objects.get(user=obj).dealer_num
0
webbyfox
7 Мар 2019 в 21:13
Расширение модели User с помощью настраиваемых полей в Django
Вы можете просто расширить профиль пользователя, создавая новую запись каждый раз, когда пользователь создается с помощью сигналов сохранения сообщений Django.
из импорта django.db.models.signals *
from __future__ импортировать unicode_literals
класс UserProfile (models.Model):
user_name = models.OneToOneField (Пользователь, related_name = 'profile')
city = models.CharField (max_length = 100, null = True)
def __unicode __ (сам): # __str__
вернуть unicode (self.имя пользователя)
def create_user_profile (отправитель, экземпляр, создано, ** kwargs):
если создано:
userProfile.objects.create (имя_пользователя = экземпляр)
post_save.connect (create_user_profile, sender = Пользователь)
Это автоматически создаст экземпляр сотрудника при создании нового пользователя.
Если вы хотите расширить модель пользователя и хотите добавить дополнительную информацию при создании пользователя, вы можете использовать django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html).Это создаст форму добавления пользователя со всеми полями, определенными в модели UserProfile.
из импорта django.db.models.signals *
from __future__ импортировать unicode_literals
класс UserProfile (models.Model):
user_name = models.OneToOneField (Пользователь)
city = models.CharField (max_length = 100)
def __unicode __ (сам): # __str__
вернуть unicode (self.user_name)
из форм импорта django
из django.forms импортировать ModelForm
из betterforms.multiform import MultiModelForm
из джанго.contrib.auth.forms импорт UserCreationForm
из .models import *
класс ProfileForm (ModelForm):
класс Мета:
model = Сотрудник
exclude = ('имя_пользователя',)
класс addUserMultiForm (MultiModelForm):
form_classes = {
'пользователь': UserCreationForm,
"профиль": ProfileForm,
}
из перенаправления импорта django.shortcuts
из .models import *
из .forms import *
из django.views.generic import CreateView
класс AddUser (CreateView):
form_class = AddUserMultiForm
template_name = "добавить пользователя.html "
success_url = '/ ваш-url-после-созданный пользователем'
def form_valid (self, form):
user = form ['пользователь']. save ()
profile = form ['profile']. save (commit = False).
profile.user_name = User.objects.get (имя пользователя = user.username)
profile.save ()
возврат перенаправления (self.success_url)
Заголовок
{% endblock%}
{% extends 'base.html'%} {% block title%} Зарегистрироваться {% endblock%} {% блокировать содержание%}{% endblock%}Зарегистрироваться
Теперь для наших urls.py
файлов на уровне проекта и приложения.
# config / urls.ру от администратора импорта django.contrib из пути импорта django.urls, включить из django.views.generic.base импортировать TemplateView urlpatterns = [ путь ('', TemplateView.as_view (template_name = 'home.html'), name = 'home'), путь ('admin /', admin.site.urls), путь ('accounts /', include ('accounts.urls')), путь ('accounts /', include ('django.contrib.auth.urls')), ]
Создайте файл urls.py
в приложении accounts
.
(учетные записи) $ touch accounts / urls.py
Затем введите следующий код:
# аккаунтов / URL.ру из пути импорта django.urls из .views импортировать SignUpView urlpatterns = [ путь ('signup /', SignUpView.as_view (), name = 'signup'), ]
Последний шаг - это наш файл views.py
в приложении accounts
, который будет содержать нашу форму регистрации.
# accounts / views.py из django.urls импортировать reverse_lazy из django.views.generic.edit импортировать CreateView из .forms import CustomUserCreationForm класс SignUpView (CreateView): form_class = CustomUserCreationForm success_url = reverse_lazy ('войти') template_name = 'регистрация / регистрация.html '
Ладно, уф! Были сделаны. Давайте проверим это.
Запустите сервер с python manage.py runserver
и перейдите на домашнюю страницу http://127.0.0.1:8000/.
Нажмите Войти в систему и используйте свои учетные данные суперпользователя .
После успешной отправки вы будете перенаправлены обратно на главную страницу и увидите персональное приветствие.
Теперь используйте ссылку выйти из системы , а затем нажмите регистрация .
Создайте нового пользователя. Мой называется testuser
. После успешной отправки формы вы будете перенаправлены на страницу входа. Войдите в систему под своим новым пользователем, и вы снова будете перенаправлены на главную страницу с персональным приветствием для нового пользователя.
Если вы хотите просмотреть страницу администратора, войдите в нее со своей учетной записью суперпользователя по адресу http://127.0.0.1:8000/admin. Если вы посмотрите на пользователей
, вы увидите двух наших пользователей.
Заключение
Теперь, когда наша пользовательская модель настроена, вы можете легко и в любое время добавить к ней дополнительные поля.Дополнительные инструкции см. В документации Django.
Вы также можете попробовать DjangoX, который представляет собой стартовую платформу Django с открытым исходным кодом, которая включает настраиваемую модель пользователя, адрес электронной почты / пароль по умолчанию вместо имени пользователя / электронной почты / пароля, социальную аутентификацию и многое другое.
Расширения модели
- документация django-extensions 3.1.2
Введение
Django Extensions предоставляет вам набор абстрактных базовых классов для моделей.
который реализует часто используемые шаблоны, такие как удержание создания модели
и даты последнего изменения.
Расширения модели базы данных
- ActivatorModel - абстрактный базовый класс, который обеспечивает статус
activate_date
иdeactivate_date
полей.
Поле статуса
- это IntegerField
, значение которого выбирается из кортежа
из вариантов - активный и неактивный - по умолчанию активен. Эта модель также
предоставляет настраиваемый менеджер, позволяющий пользователю легко запрашивать активные или
неактивные объекты.
Например: Model.objects.active ()
возвращает все экземпляры Model
, которые имеют
активный статус.
- TitleDescriptionModel - эта модель абстрактного базового класса предоставляет
полей заголовка
иописания
.
Поле заголовка
- CharField
с максимальной длиной 255 символов,
не допускающий значения NULL. описание
. С другой стороны, описание
- это
Обнуляемое Текстовое поле
.
- TimeStampedModel - модель абстрактного базового класса, обеспечивающая самоуправляемую
создал
иизменил
полей.
Оба поля определены в расширениях Django как
CreationDateTimeField
и ModificationDateTimeField
.
Эти поля являются подклассами Django DateTimeField
и будут хранить
значение django.utils.timezone.now ()
при создании модели
и модификация соответственно
- TitleSlugDescriptionModel - модель абстрактного базового класса, которая, как и
TitleDescription Модель
, содержитзаголовок
иописание
полей
но также предоставляет самоуправляемое полеslug
, которое заполняется из заголовка.
Класс этого поля является настраиваемым AutoSlugField, основанным на Django's
SlugField
. По умолчанию в качестве разделителя используется –
, он уникален и делает
не принимать пустые значения.
Можно настроить slugify_function
путем определения вашей пользовательской функции в модели:
# models.pyиз моделей импорта django.db
из django_extensions.db.models импортировать TitleSlugDescriptionModel
класс MyModel (TitleSlugDescriptionModel, models.Model):
def slugify_function (self, content):
"" "
Эта функция будет использоваться для обозначения
заголовок (поле по умолчанию populate_from)
"" "
вернуть контент.