Добавление кода и методов в Django Model нарушает его - PullRequest
0 голосов
/ 31 октября 2018

У меня есть модель Django, похожая на эту:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)

Я хотел добавить код человеку, за пределами файла models.py. Поэтому я попытался импортировать его, наследовать от него и добавить код: например:

class MyPerson(db.Person):
    def __init__(self, person_name):
        super(MyPerson, self).__init__(name=person_name)

    def print_person_info(self):
        print(self.name)

Я получаю сообщение об ошибке, похожее на это:

RuntimeError: Класс модели db.persons.models.Person не объявляет явную метку app_label и не находится в приложении в INSTALLED_APPS.

хотя, конечно, в моем файле settings.py я добавляю свое приложение persons в INSTALLED_APPS

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

Есть идеи?

В целом нормально / рекомендуется наследовать от модели?

1 Ответ

0 голосов
/ 31 октября 2018

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

Если вы наследуете модель Django. Джанго видит это как модель extra (которая наследует). Поэтому он должен создать дополнительную таблицу на стороне базы данных, которая имеет ссылку на «родительский объект», и в некоторых случаях ваши дополнительные поля указывают их. Но так как вы, вероятно, определили этот класс вне models.py, он не может найти app_label, и в результате многие задачи не могут быть выполнены.

В целом нормально / рекомендуется наследовать от модели?

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

Обычно, если вы хотите добавить поведение, вы делаете это непосредственно в классе модели , например:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)

    def print_person_info(self):
        print(self.name)

или в случае, если поведение отличается от того, что вы уже определили, вы можете использовать модель прокси [Django-doc] , чтобы позволить двум классам модели работать с одной и той же таблицей базы данных. каждый со своим поведением, вроде:

class MyPerson(db.Person):

    class Meta:
        <b>proxy = True</b>

    def print_person_info(self):
        print(self.name)

Но прокси-сервер также может внести много дополнительных «сложностей», и поэтому рекомендуется использовать его только как «последнее средство».

На самом деле рекомендуется , а не для исправления функции __init__, и определенно не путем изменения параметров (если вы это сделаете, используйте *args и **kwargs для передачи всех параметров), как:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.TextField(unique=False)

    def __init__(self, *args, **kwargs):
        # ... (do something) ...
        super(Person, self).__init__(*args, **kwargs)
        # ... (do something) ...

    def print_person_info(self):
        print(self.name)

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

...