Наследование от ABC и django.db.models.Model вызывает исключение метакласса - PullRequest
0 голосов
/ 29 апреля 2018

Я пытаюсь реализовать класс модели данных Django, который также является классом интерфейса, с использованием Python 3. Моя причина для этого заключается в том, что я пишу базовый класс для своего коллеги и мне нужно, чтобы он реализовал три метода во всех классах он происходит от моего. Я пытаюсь дать ему упрощенный способ использования функциональности системы, которую я разработал. Но он должен переопределить несколько методов, чтобы предоставить системе достаточно информации для выполнения кода в его унаследованных классах.

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

from django.db import models
from abc import ABC, abstractmethod

class AlgorithmTemplate(ABC, models.Model):
    name = models.CharField(max_length=32)

    @abstractmethod
    def data_subscriptions(self):
        """
        This method returns a list of topics this class will subscribe to using websockets

        NOTE: This method MUST be overriden!

        :rtype: list
        """

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

Проблема


После включения класса, подобного приведенному выше, в мой проект и запуска python manage.py makemigrations я получаю ошибку: TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases. Я искал переполнение стека, но нашел только решения, подобные следующему:

class M_A(type): pass
class M_B(type): pass
class A(metaclass=M_A): pass
class B(metaclass=M_B): pass

class M_C(M_A, M_B): pass
class C:(A, B, metaclass=M_C): pass

Я прочитал следующие сообщения:

Использование ABC, PolymorphicModel, django-models дает конфликт метакласса

python 3: TypeError: конфликт метаклассов: метакласс производного класса должен быть (нестрогим) подклассом метаклассов всех его баз

И я попробовал много вариантов этих решений, но я все еще получаю страшное исключение metaclass. Помоги мне Оби-Ван Кеноби, ты моя единственная надежда. : -)

1 Ответ

0 голосов
/ 29 апреля 2018

Я нашел решение, которое сработало для меня, поэтому подумал, что я опубликую его здесь на случай, если оно поможет кому-то еще. Я решил не наследовать от класса ABC, а вместо этого просто вызвать исключение в «абстрактных» методах (тех, которые должен реализовать производный класс). Я нашел полезную информацию в документах Django, описывающих использование моделей данных Django в качестве базового класса Abstract, а также наследование нескольких таблиц.

Модель данных Django как абстрактный базовый класс


Цитируется из Документы :

Абстрактные базовые классы полезны, когда вы хотите поместить некоторую общую информацию в ряд других моделей. Вы пишете свой базовый класс и помещаете abstract = True в мета-класс. Эта модель не будет использоваться для создания таблицы базы данных. Вместо этого, когда он используется в качестве базового класса для других моделей, его поля будут добавлены к полям дочернего класса.

Пример:

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Модель Студента будет иметь три поля: имя, возраст и домашняя группа. Модель CommonInfo не может использоваться как обычная модель Django, так как она абстрактный базовый класс Он не генерирует таблицу базы данных или иметь менеджера, и не может быть создан или сохранен напрямую.

Поля, унаследованные от абстрактных базовых классов, могут быть переопределены с помощью другое поле или значение, или удаляется с помощью None.


Наследование нескольких таблиц с моделью данных Django


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

Цитируется из Документы :

Второй тип наследования моделей, поддерживаемый Django, - это когда каждый Модель в иерархии - это модель сама по себе. Каждая модель соответствует своей таблице базы данных и может быть запрошен и создан индивидуально. Отношения наследования вводят связи между модель ребенка и каждый из его родителей (через автоматически созданный OneToOneField). Например:

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

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

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
...