Как заставить поле модели Django получать свое значение из другого поля и быть недоступным для редактирования - PullRequest
0 голосов
/ 24 октября 2019

У меня есть сценарий использования, в котором я создал пользовательскую модель пользователя в инфраструктуре отдыха Django и другую модель под названием Book, которая создается пользователем. Мои модели выглядят следующим образом:

from django.db import models
from django.contrib.auth.models import (
    AbstractBaseUser,
    BaseUserManager,
    PermissionsMixin)
from django.conf import settings


class UserManager(BaseUserManager):
    def create_user(self, email, password=None, author_pseudonm=None, **extra_fields):
        """Creates and saves a new user """
        if not email:
            raise ValueError('Users must have an email address')
        if not author_pseudonm:
            raise ValueError("User must have an author pseudo name field")
        user = self.model(email=self.normalize_email(email),
                          author_pseudonm=author_pseudonm, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password, author_pseudonm):
        """Creates and saves a new super user"""
        user = self.create_user(
            email=email, password=password, author_pseudonm=author_pseudonm)
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):
    """Custom user model which supports using email instead of username"""
    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)
    author_pseudonm = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ["author_pseudonm"]


class Book(models.Model):
    """Custom book model"""
    title = models.CharField(max_length=255, unique=True)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )
    description = models.TextField()
    price = models.IntegerField()
    author = models.CharField(default=user.author_pseudonm)
    is_published = models.BooleanField(default=True)

    def __str__(self):
        return self.title

В модели книги у меня есть поле с именем пользователя, которое в основном является внешним ключом, связывающим созданную книгу с тем, кто создал эту книгу, и другое поле, называемое автором, которое в основном является полем. вызывается author_pseudonm из пользовательской модели.

Я очень новичок в остальной среде, и мне было интересно, если это правильный способ сделать это.

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

Пожалуйста, предложите, как я могу добиться того же, используя остальные рамки.

Ответы [ 2 ]

2 голосов
/ 24 октября 2019

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

Способ, которым яэто будет иметь пользовательскую функцию save, которая с учетом внешнего ключа User получает значение author_pseudonym и вводит его в виде поля author и сохраняет модель. Вы можете поставить флаг editable=False в определении поля author, чтобы в будущем его никто случайно не отредактировал.

Ниже приведен псевдокод, но я представляю вашу функцию save для Book будет выглядеть примерно так:

def save(self, *args, **kwargs):
    user = self.user
    self.author = user.author_pseudonm
    super(Book, self).save(**kwargs)

Для записи, models часть DRF и ванильный Django одинаковы. Вы бы достигли этого одинаково независимо от того, используете ли вы DRF, потому что это относится только к моделям.

2 голосов
/ 24 октября 2019

По сути, вы не хотите дублировать данные таким образом - вам не нужно хранить author в вашей Book модели, так как она уже находится в вашей User модели. Всякий раз, когда вам нужно получить псевдоним автора для данной книги, вы должны просто сделать

book.user.author_pseudonm

или если вы хотите сослаться на столбец в Django admin или сериализаторах или фильтрах наборов запросов, вы можете сделать этоиспользуя user__author_pseudonm

(Примечание: здесь вы, похоже, тоже опечатка author_pseudonm -> author_pseudonym)

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