Django Model Mixins: успадкування від models.odel або від об'єкта?


79

Це питання про міксини Python, яке може бути корисним загалом. Я просто використовую моделі Django, оскільки це той варіант використання, який мені найбільш відомий.

Чи повинен міксин успадковуватись від класу, який він призначений для змішування з або від 'об'єкта'?

Приклади за кодом, що є правильнішим чи кращим чи кращим залежно від того, чого ви хочете досягти?

Це

class TaggingMixin(models.Model):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(models.Model, TaggingMixin):
    title = models.CharField(max_length=100)

Або це:

class TaggingMixin(object):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(models.Model, TaggingMixin):
    title = models.CharField(max_length=100)

Я думаю, що успадкування від об’єкта - це правильний шлях. Але я бачу приклади першого випадку по всій мережі ...

EDIT: Я переніс своє подальше запитання на окреме питання: Django Abstract Models vs simple Python mixins vs Python ABCs

Відповіді:


83

Джанго робить багато мета-магії, коли справа стосується своїх класів моделей, тому, на жаль, звичайний підхід до міксинів, як пропонується у відповіді Даніеля Роузмена - звідки вони успадковують object- погано працює у Всесвіті Джанго.

Правильний спосіб структурувати ваші міксини, використовуючи наведений приклад, буде:

class TaggingMixin(models.Model):
    tag = models.ForeignKey(Tag)

    class Meta:
        abstract = True

class MyModel(TaggingMixin):
    title = models.CharField(max_length=100)

Важливими моментами тут є:

  • Mixins успадковуються від, model.Modelале налаштовуються як абстрактний клас.
  • Оскільки міксини успадковують від model.Model, ваша фактична модель не повинна успадковувати від нього. Якщо ви це зробите, це може спричинити послідовний виняток порядку роздільної здатності методу.

1
Це призведе до TypeError: Cannot create a consistent method resolution order (MRO). Робіть class MyModel(TaggingMixin):замість цього. Див stackoverflow.com/q/29214888/1627479
Joren

Дякую @Joren. Відредаговано відповідь, щоб відобразити це.
jsdalton

22
"Міксин" тут неправильний термін. Це просто абстрактна модель. Ви не можете "змішувати" його з models.Modelіншими абстрактними моделями
Девід Авсаянішвілі

15

Я б рекомендував, щоб він успадковував від object. Таким чином ви можете гарантувати, що він надає лише ті методи та атрибути, які ви насправді чітко визначаєте.

Крім того , ви завжди повинні переконатися , що ви поклали підмішати клас перший , коли описуєте свій клас бетону. Правила роздільної здатності Python означають, що суперкласи шукаються в порядку їх визначення у оголошенні класу, а роздільна здатність зупиняється, коли знайдений відповідний атрибут. Отже, якщо ваш міксин визначає метод, який також визначається основним суперкласом, ваш метод мікшину не буде знайдений.


12
За винятком магії метакласу, яка додає поля, не працює, якщо ваш клас mixin не успадковує models.Model(або, точніше, не має того, __metaclass__що потрібно).
Matthew Schinckel

2
Успадкування об’єкта у мене не спрацювало. Див: stackoverflow.com/questions/17343867 / ...
utapyngo

2
наслідувати об'єкт - це НЕ хороший спосіб для django. тому що django makemigrations не можуть його розпізнати. файли міграції не містять поданих.
9nix00

Було б непогано додати невеликий приклад із шаблоном.
Пітікос,

8

Це виглядає як робота для абстрактної моделі .

РЕДАГУВАТИ:

Це не міксини як такі. Вірніше, їм не потрібно бути. Ви можете безпосередньо вивести абстрактну модель.


1
Помилка, так, ви маєте рацію, це робота для абстрактної моделі, насправді я просто забув їх у коді: s Я додав, але зараз я починаю ще більше заплутуватися у власному питанні .. .
hopla

3

Коли ви успадковуєте від простого об'єкта Python, South не створює міграцію, тому ви не можете використовувати цей підхід


1
Це не має нічого спільного з південними міграціями.
Matthew Schinckel

Я маю на увазі, що такий підхід погано грає з Півднем, що для мене є великою проблемою
Харандзюк,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.