Django - расширение пользовательской модели с помощью профиля, но также другого типа пользователя - PullRequest
0 голосов
/ 24 марта 2019

Я хочу расширить пользовательскую модель в Django (2.2) и объединить ее с сущностями Host и Guest, которые также имеют определенные поля.

В официальной документации рекомендуется создать класс "Профиль" с полем OneToOne, которое ссылается на первичный ключ пользователя.

Я вижу 3 способа сделать это:

Решение 1: Профиль, модель хоста и гостя:

class Profile(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)

class Host(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    host_field= models.CharField(max_length=500)

class Guest(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    guest_field = models.BooleanField(null=False)

Решение 2. Модель хоста и гостя (с дублированием полей профиля)

class Host(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    host_field = models.CharField(max_length=500)

class Guest(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    guest_field = models.BooleanField(null=False)

Решение 3. Модель профиля (содержит поля «Гость» и «Хост»)

class Profile(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)
    is_host = models.BooleanField(null=False)       
    guest_field = models.BooleanField(null=False) 
    host_field = models.CharField(max_length=500) 

Все эти решения работают.

Мой вопрос: «Какой из них самый умный, учитывая все обстоятельства» (меньше доступа к базе данных, меньше кода для написания, проще в обслуживании, меньше ограничений и т. Д.)

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

После более глубокого изучения документации Django и прочтения статьи , упомянутой @ sam , в которой объясняется, как реализовать многопользовательские типы в Django, я нашел свой ответ.

Он написан в Django doc о том, что «настоятельно рекомендуется настроить пользовательскую модель пользователя, даже если вам достаточно модели пользователя по умолчанию».

Вот что она дает в моем случае:

class User(AbstractUser):
    is_guest = models.BooleanField(default=False)
    is_host = models.BooleanField(default=False)
    language = models.CharField(max_length=2)


class Host(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    host_field = models.CharField(max_length=500)   


class Guest(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    guest_field = models.BooleanField(null=False)

в settings.py:

AUTH_USER_MODEL = 'path.to.User'

Запись гостя или хоста вставляется при создании нового пользователя:

  user = User.objects.create_user(...)

  if is_host:
        Host.objects.create(user=user)
  else:
        Guest.objects.create(user=user)

Я ценю тот факт, что могуопределить пользовательский «тип» в объекте запроса (с помощью request.user.is_host).

Расширяя класс пользователя, вы также можете использовать поле email для входа в систему и сделать его уникальным:

class User(AbstractUser):
    [...]
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

Если однажды в производстве вы решили добавить поля в пользовательскую модель, возможно, если вы настроили пользовательскую модель.

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

0 голосов
/ 24 марта 2019

Я бы предложил 4-й способ, используя миксин с абстрактной моделью.Это выведет поля абстрактной модели к тем, к которым вы ее применяете.Таким образом, вам не нужно переписывать код и применять его к разным моделям:

class ProfileMixin(models.Model):
    k_user = models.OneToOneField(User, on_delete=models.CASCADE)
    language = models.CharField(max_length=2)

    class Meta:
        abstract = True

class Host(ProfileMixin):
    host_field = models.CharField(max_length=500)

class Guest(ProfileMixin):
    guest_field = models.BooleanField(null=False)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...