Rozszerzenie modelu Użytkownika o niestandardowe pola w Django

Jaki jest najlepszy sposób na rozszerzenie modelu użytkownika (w pakiecie z aplikacją uwierzytelniania Django) o niestandardowe pola? Chciałbym również ewentualnie użyć e-maila jako nazwy użytkownika (do celów uwierzytelniania).

Widziałem już kilka sposoby , Aby to zrobić, ale nie może się zdecydować, który z nich jest najlepszy.

Author: Dmitriy, 2008-09-04

10 answers

Najmniej bolesnym i rzeczywiście zalecanym przez Django sposobem na zrobienie tego jest Właściwość OneToOneField(User).

Rozszerzenie istniejącego modelu użytkownika

Jeśli chcesz przechowywać informacje związane z User, możesz użyć relacji jeden do jednego do modelu zawierającego pola w celu uzyskania dodatkowych informacji. Ten model jeden do jednego jest często nazywany modelem profilu, ponieważ może przechowywać informacje dotyczące witryny nie związane z auth użytkownik.

To powiedziawszy, Rozszerzanie django.contrib.auth.models.User i zastępowanie go również działa...

Zastępowanie niestandardowego modelu użytkownika

Niektóre rodzaje projektów mogą mieć wymagania uwierzytelniania, dla których Wbudowany Model User Django nie zawsze jest odpowiedni. Na przykład w niektórych witrynach bardziej sensowne jest używanie adresu e-mail jako tokena identyfikacyjnego zamiast nazwy użytkownika.

[Ed: dwa ostrzeżenia i powiadomienie następują , wspominając, że to jest dość drastyczne .]

Zdecydowanie trzymałbym się z dala od zmiany rzeczywistej klasy użytkownika w drzewie źródłowym Django i/lub kopiowania i zmieniania modułu auth.

 216
Author: Ryan Duffield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-13 00:38:44

Uwaga: Ta odpowiedź jest przestarzała. zobacz inne odpowiedzi, jeśli używasz Django 1.7 lub nowszego.

Tak to robię.
#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'

Spowoduje to utworzenie userprofile za każdym razem, gdy użytkownik zostanie zapisany, jeśli zostanie utworzony. Następnie możesz użyć

  user.get_profile().whatever

Oto więcej informacji z docs

Http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

Aktualizacja: Należy pamiętać, że {[2] } jest przestarzały od wersji 1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module

 213
Author: Raisins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-14 11:49:34

Cóż, minęło trochę czasu od 2008 roku i nadszedł czas na jakąś świeżą odpowiedź. Od Django 1.5 będziesz mógł stworzyć własną klasę użytkownika. Właściwie, w czasie, gdy to piszę, jest już scalony w master, więc możesz go wypróbować.

Jest kilka informacji na ten temat w docslub jeśli chcesz zagłębić się w to głębiej, w this commit.

Wszystko, co musisz zrobić, to dodać AUTH_USER_MODEL do ustawień ze ścieżką do niestandardowej klasy użytkownika, która rozszerza AbstractBaseUser (bardziej konfigurowalny Wersja) lub AbstractUser (mniej lub bardziej stara Klasa użytkownika, którą można rozszerzyć).

Dla osób, które są leniwe, aby kliknąć, oto przykład kodu (zaczerpnięty z 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
 180
Author: Ondrej Slinták,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-24 15:41:18

Istnieje oficjalne zalecenie dotyczące przechowywania dodatkowych informacji o użytkownikach . Książka Django omawia również ten problem w sekcji Profile .

 41
Author: Dmitry Mukhin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 13:52:24

Od Django 1.5 możesz łatwo rozszerzyć model użytkownika i utrzymać jedną tabelę w bazie danych.

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

Musisz również skonfigurować ją jako bieżącą klasę użytkownika w pliku ustawień

# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"

Jeśli chcesz dodać wiele preferencji użytkowników, opcja OneToOneField może być lepszym wyborem.

Uwaga dla osób rozwijających biblioteki innych firm: jeśli potrzebujesz dostępu do klasy user pamiętaj, że ludzie mogą ją zmienić. Użyj oficjalnego pomocnika, aby uzyskać prawo klasa

from django.contrib.auth import get_user_model

User = get_user_model()
 39
Author: Riccardo Galli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-20 21:56:43

Poniżej znajduje się kolejne podejście do rozszerzenia użytkownika. Wydaje mi się,że jest bardziej przejrzysty,łatwy, czytelny niż powyżej dwóch podejść.

Http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

Przy użyciu powyższego podejścia:

  1. nie musisz używać użytkownik.get_profile ().newattribute aby uzyskać dostęp do dodatkowych informacji powiązane z użytkownikiem
  2. możesz po prostu uzyskać bezpośredni dostęp dodatkowe nowe atrybuty poprzez użytkownik.newattribute
 21
Author: Rama Vadakattu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 13:01:09

Możesz po prostu rozszerzyć profil użytkownika, tworząc nowy wpis za każdym razem, gdy użytkownik jest tworzony za pomocą sygnałów zapisywania postów django

Models.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User, related_name='profile')
    city = models.CharField(max_length=100, null=True)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

def create_user_profile(sender, instance, created, **kwargs):
    if created:
    userProfile.objects.create(userName=instance)

post_save.connect(create_user_profile, sender=User)

Spowoduje to automatyczne utworzenie instancji pracownika, gdy zostanie utworzony nowy użytkownik.

Jeśli chcesz rozszerzyć model użytkownika i chcesz dodać więcej informacji podczas tworzenia użytkownika, możesz użyć django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html ). spowoduje to utworzenie formularza dodawania użytkownika z wszystkie pola zdefiniowane w modelu userProfile.

Models.py

from django.db.models.signals import *
from __future__ import unicode_literals

class userProfile(models.Model):

    userName = models.OneToOneField(User)
    city = models.CharField(max_length=100)

    def __unicode__(self):  # __str__
        return unicode(self.userName)

Forms.py

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 = ('userName',)


class addUserMultiForm(MultiModelForm):
    form_classes = {
        'user':UserCreationForm,
        'profile':profileForm,
    }

Views.py

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 = "addUser.html"
    success_url = '/your url after user created'

    def form_valid(self, form):
        user = form['user'].save()
        profile = form['profile'].save(commit=False)
        profile.userName = User.objects.get(username= user.username)
        profile.save()
        return redirect(self.success_url)

AddUser.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="." method="post">
            {% csrf_token %}
            {{ form }}     
            <button type="submit">Add</button>
        </form>
     </body>
</html>

Urls.py

from django.conf.urls import url, include
from appName.views import *
urlpatterns = [
        url(r'^add-user/$', addUser.as_view(), name='addDistributor'),
]
 10
Author: Atul Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-04 15:44:25

Rozszerzenie modelu użytkownika Django (UserProfile) jak Pro

Znalazłem to bardzo przydatne: link

Ekstrakt:

Z django.contrib.auth.models import User

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
 7
Author: Massimo Variolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 14:38:18

Nowość w Django 1.5, teraz możesz stworzyć swój własny model użytkownika (co wydaje się być dobrą rzeczą do zrobienia w powyższym przypadku). Zobacz 'dostosowywanie uwierzytelniania w Django'

Prawdopodobnie najfajniejsza nowa funkcja w wydaniu 1.5.

 2
Author: chhantyal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-12 10:10:13

To jest to, co robię i jest to moim zdaniem najprostszy sposób, aby to zrobić. zdefiniuj Menedżera obiektów dla nowego niestandardowego modelu, a następnie zdefiniuj model.

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

Nie zapomnij dodać tej linii kodu w settings.py:

AUTH_USER_MODEL = 'YourApp.User'
To jest to, co robię i to zawsze działa.
 0
Author: Milad Kh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-25 05:00:38