Настройка двух разных типов пользователей в Django 1.5/1.6

Обратите внимание - это обновленная версия моего первоначального вопроса по этому вопросу, но заслуживает того, чтобы вас снова попросили с изменением того, как Django занимается с пользователями и аутентификации.

Я работаю над сайтом с двумя разными пользователями - позвоните им Customers и Store Owners. Оба регистрируются на сайте, но имеют очень разную функциональность. Customers просто имеет один профиль и может делать покупки среди магазинов, которые им нравятся. Store Owners имеют одну учетную запись, но могут иметь доступ к нескольким магазинам, и каждый магазин может иметь несколько Store Owners.

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

Customer
  email (username)
  password
  name
  address
  time_zone
  preferred_shipping
  favorite_stores (many-to-many field)
  ...

Store Owner
  email (username)
  password
  name
  balance
  stores_owned (many-to-many field on Stores)
  stores_managed (many-to-many field on Stores)
  ...
Первоначально, когда у Django была плохая пользовательская поддержка, у меня был класс UserProfile с некоторыми дополнительными полями с OneToOne на User, а затем дополнительные классы Customer и StoreOwner, которые были OneToOne на UserProfile. Это не очень хорошо работает.

Учитывая изменения в Django 1.5/1.6, я пытаюсь найти лучший способ структурировать это. Сейчас у меня есть следующее:

class CustomerUser(AbstractBaseUser):
    ...

class StoreOwnerUser(AbstractBaseUser):
    ...

Но поскольку у пользователя будет два типа пользователей, я не могу установить AUTH_USER_MODEL только один из них.

Каков наилучший способ структурирования этого, так что у меня могут быть два разных типа пользователей с разными полями, без каких-либо проблем с аутентификацией пользователя, созданием пользователя или администратором?

Кроме того, как я могу определить только логин, является ли этот пользователь CustomerUser или StoreOwnerUser?

Ответ 1

Похоже, что есть некоторые общие функции и необычные функции для ваших типов пользователей. Если в ваших пользовательских типах есть общие черты, то пользовательская модель Django по умолчанию не поддерживается из коробки, вы должны подклассифицировать ее напрямую.

Добавление дополнительных, необычных функций к вашим типам пользователей лучше всего делать не путем подкласса, а с помощью профиля. Мое обоснование для этого состоит в том, что ваша аутентификация для этих типов пользователей принципиально не меняется, но информация о пользователе выполняется в зависимости от типа пользователя. Чтобы разместить это, вы создаете отдельную модель с этими подробностями и ссылаетесь на свой класс User как отношение OneToOne/ForeignKey (в зависимости от вашего дизайна).

Вы можете внести изменения в свой процесс создания пользователя, чтобы определить, какой тип пользователя он должен быть, и установить его связанный OneToOneField/ForeignKey (в зависимости от вашего дизайна) с соответствующей моделью типа клиента.

Таким образом, вы должны иметь только один AUTH_USER_MODEL, и вы сможете обрабатывать детали для разных типов клиентов.

Ответ 2

Каков наилучший способ структурирования этого, чтобы у меня было два разные типы пользователей с разными полями, не заставляя меня проблемы в аутентификации пользователя, создание пользователя или администратор?

У вас фактически есть только один тип пользователей. Просто у некоторых пользователей есть определенные свойства, а другие нет. Подумайте, как у django есть "пользователи" и "администраторы". Они являются экземплярами одной и той же модели, но с разными свойствами и разрешениями.

Вы должны подойти аналогично. У вас есть одна модель пользователя для всего вашего приложения. Вы можете установить свойства/методы в своем пользовательском классе, чтобы определить, какие флаги установлен этим пользователем (что определяло бы "тип" пользователя).

Кроме того, как я могу определить только логин, является ли этот пользователь a CustomerUser или StoreOwnerUser?

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

Ответ 3

  • Создайте BaseUser, который расширяет базу данных Django.
  • Создайте два подкласса, названный CustomerUser и StoreOwnerUser, который расширяет BaseUser

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class BaseUser(AbstractUser):
        # all the common fields go here, for example:
        email = models.EmailField(max_length=10,unique=True)
        name = models.CharField(max_length=120)
    
    class StoreOwnerUser(BaseUser):
        # All Store Owner specific attribute goes here
        balance = models.some_balance_field()
        stores_owned = models.some_stores_owned_field()
    
        class Meta:
        verbose_name = 'Store Owner'
    
    class CustomerUser(BaseUser):
        # All Customer specific attribute goes here
        customer_id = models.CharField(max_length=30, unique=True)
        address =  models.some_address
        time_zone = models.something...
        ...
    
        class Meta:
            verbose_name = 'Customer'