Django - разрешить дублирование имен пользователей - PullRequest
10 голосов
/ 08 января 2010

Я работаю над проектом в django, который требует наличия отдельных групп пользователей в их собственном пространстве имен username.

Так, например, у меня может быть несколько «организаций», и username должен быть уникальным только внутри этой организации.

Я знаю, что могу сделать это, используя другую модель, которая содержит имя пользователя / идентификатор организации, но при этом все еще оставляет это бесполезное (и обязательное) поле в defualt django auth User, которое мне нужно будет заполнить чем-то. 1008 *

Я уже написал собственный auth backend, который аутентифицирует пользователя по LDAP. Однако, как я упоминал ранее, я все еще сталкиваюсь с проблемой заполнения / игнорирования поля username для пользователя django по умолчанию.

Есть ли способ отменить ограничение уникальности для username для пользователей аутентификации Django?

Ответы [ 5 ]

8 голосов
/ 08 января 2010

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

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

from django.contrib.auth.models import User

User._meta.get_field('username')._unique = False

Обратите внимание, что это не изменит ограничение уникальности базы данных для таблицы auth_user, если оно уже было создано. Поэтому вам нужно внести это изменение до того, как запустит syncdb. В качестве альтернативы, если вы не хотите воссоздавать свою таблицу auth_user, вы можете внести это изменение, а затем вручную изменить таблицу базы данных, чтобы удалить ограничение.

6 голосов
/ 08 января 2010

Что вы можете сделать, это расширить пользовательскую модель. Для таблицы User создайте имя пользователя (например, A_123, A_345), которое вообще не будет отображаться на сайте.

Затем создайте новую модель, расширяющую User.

class AppUser(User):
    username = models.CharField...
    organization = models.CharField...

Затем вы создаете пользовательский сервер аутентификации, который использует AppUser вместо объекта User.

1 голос
/ 08 января 2010

Мне лично не нужно было искать решение этой проблемы, но одним из способов решения этой проблемы (с точки зрения SAAS) было бы добавление префикса имени пользователя к организационному идентификатору (предполагая уникальные организации). Например: subdomain.yoursite.com будет приравнивать пользователя с именем пользователя: subdomain_username. Вам просто нужно кодировать некоторую бизнес-логику при входе в поддомен, чтобы привязать ее к имени пользователя.

0 голосов
/ 13 августа 2018

Я тоже страдал с этой проблемой. Я делал проект, где я должен был использовать электронную почту, а мобильный - нет. как поля входа в систему, но ни одно из них не должно быть уникальным, потому что это были разные типы пользователей, и пользователь может иметь более одного объекта пользователя, а также для проекта требуется только одна таблица авторизации пользователя (Право!)

Поэтому я расширил класс AbstractBaseUser, где я мог бы изменить атрибут USERNAME_FIELD. Вот как: -

from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import PermissionsMixin

# Custom model for User
class User(AbstractBaseUser, PermissionsMixin):

    first_name = models.CharField(max_length=100, blank=False)
    last_name = models.CharField(max_length=100, blank=True)
    password = models.CharField(max_length=255, blank=False)
    email = models.EmailField(max_length=255, blank=False)
    mobile = models.CharField(max_length=12)
    user_type = models.ForeignKey(UserTypes, on_delete=models.DO_NOTHING)
    is_approved = models.BooleanField(default=False)

    objects = UserManager()
    # Here's the Catch
    USERNAME_FIELD = 'id'

    def get_full_name(self):
        '''
        Returns the first_name plus the last_name, with a space in between.
        '''
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        '''
        Returns the short name for the user.
        '''
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        '''
        Sends an email to this User.
        '''
        send_mail(subject, message, from_email, [self.email], **kwargs)

    class Meta:
        db_table = 'user'

Да, точно, удивлен? USERNAME_FIELD должно быть уникальным полем, ограничивающим этот атрибут. Я не мог использовать электронную почту или мобильный нет. как уникальное поле.

Затем я создал собственный менеджер для удаления поля имени пользователя (ссылка = https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#abstractbaseuser)

from django.contrib.auth.base_user import BaseUserManager


class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)

Это поможет.

0 голосов
/ 27 июня 2013

Я столкнулся с точно такой же проблемой, и я много читал (о том, как решить эту проблему в 1.5), и я просто подумал о гораздо более простом решении. Что если вы просто добавите префикс фиксированной длины с идентификатором организации для хранения имени пользователя?

т.е. Идентификатор организации = 115, выбранное имя пользователя = "john" и фиксированная длина 6. Таким образом, в базе данных вы сохраняете имя пользователя "000115_john".

Когда вы входите в систему, вы просто соединяете два параметра и пытаетесь аутентифицироваться с помощью Django. Я не уверен, строго ли необходима фиксированная длина, но мог бы избежать нежелательных результатов, если пользователь выбирает имя пользователя только с цифрами.

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