Я собираюсь сделать это:
class Place(models.Model):
name = models.CharField(max_length=20)
rating = models.DecimalField()
class LongNamedRestaurant(Place): # Subclassing `Place`.
name = models.CharField(max_length=255) # Notice, I'm overriding `Place.name` to give it a longer length.
food_type = models.CharField(max_length=25)
Это версия, которую я хотел бы использовать (хотя я открыт для любых предложений): http://docs.djangoproject.com/en/dev/topics/db/models/#id7
Поддерживается ли это в Django? Если нет, есть ли способ добиться аналогичных результатов?
python
django
django-inheritance
Джонни 5
источник
источник
Ответы:
Обновленный ответ: как люди отметили в комментариях, исходный ответ не отвечал должным образом на вопрос. Действительно,
LongNamedRestaurant
в базе данных создавалась только модель,Place
не было.Решение состоит в том, чтобы создать абстрактную модель, представляющую «Место», например.
AbstractPlace
, и наследовать от него:Также прочитайте ответ @Mark , он дает отличное объяснение, почему вы не можете изменить атрибуты, унаследованные от неабстрактного класса.
(Обратите внимание, что это возможно только с Django 1.10: до Django 1.10 изменение атрибута, унаследованного от абстрактного класса, было невозможно.)
источник
Place
был абстрактным, поэтому он не был создан в базе данных. Но OP хотел, чтобы и то,Place
и другоеLongNamedRestaurant
было создано в базе данных. Поэтому я обновил свой ответ, добавивAbstractPlace
модель, которая является «базовой» (т. Е. Абстрактной) модельюPlace
иLongNamedRestaurant
унаследована от нее. Теперь обаPlace
иLongNamedRestaurant
создаются в базе данных, как просил OP.Нет, это не так :
источник
User._meta.get_field('email').required = True
может сработать, не совсем уверена._meta
соответствии с родительским классом, напримерMyParentClass._meta.get_field('email').blank = False
(чтобы сделать унаследованноеemail
поле обязательным в Admin)Это невозможно, если не абстрактно, и вот почему:
LongNamedRestaurant
также является aPlace
, не только как класс, но и в базе данных. Таблица мест содержит запись для каждого чистогоPlace
и для каждогоLongNamedRestaurant
.LongNamedRestaurant
просто создает дополнительную таблицу с символомfood_type
и ссылкой на таблицу мест.Если вы это сделаете
Place.objects.all()
, вы также получите каждое место, которое является aLongNamedRestaurant
, и оно будет экземпляромPlace
(безfood_type
). Таким образом, они используют одинPlace.name
иLongNamedRestaurant.name
тот же столбец базы данных и, следовательно, должны быть одного типа.Я думаю, это имеет смысл для обычных моделей: каждый ресторан - это место, и в нем должно быть по крайней мере все, что есть в нем. Возможно, эта согласованность также является причиной того, что абстрактные модели были невозможны до 1.10, хотя это не создавало проблем с базой данных. Как отмечает @lampslave, это стало возможным в 1.10. Я лично рекомендую соблюдать осторожность: если Sub.x переопределяет Super.x, убедитесь, что Sub.x является подклассом Super.x, иначе Sub не может использоваться вместо Super.
Обходные пути : вы можете создать собственную модель пользователя (
AUTH_USER_MODEL
), которая включает в себя довольно много дублирования кода, если вам нужно только изменить поле электронной почты. В качестве альтернативы вы можете оставить электронное письмо как есть и убедиться, что оно требуется во всех формах. Это не гарантирует целостность базы данных, если ее используют другие приложения, и не работает наоборот (если вы хотите, чтобы имя пользователя не требовалось).источник
См. Https://stackoverflow.com/a/6379556/15690 :
источник
Вставил свой код в новое приложение, добавил приложение в INSTALLED_APPS и запустил syncdb:
Похоже, Django этого не поддерживает.
источник
Этот супер-крутой фрагмент кода позволяет вам «переопределять» поля в абстрактных родительских классах.
Когда поля были удалены из абстрактного родительского класса, вы можете переопределить их по своему усмотрению.
Это не моя собственная работа. Исходный код отсюда: https://gist.github.com/specialunderwear/9d917ddacf3547b646ba
источник
Может быть, вы могли бы разобраться с assign_to_class:
Syncdb отлично работает. Я не пробовал этот пример, в моем случае я просто переопределил параметр ограничения, так что ... подождите и посмотрите!
источник
Place._meta.get_field('name').max_length = 255
в теле класса должно работать без переопределения__init__()
. Тоже было бы короче.Я знаю, что это старый вопрос, но у меня была аналогичная проблема, и я нашел обходной путь:
У меня были следующие занятия:
Но я хотел, чтобы унаследованное от года поле изображения было обязательным, при этом поле изображения суперкласса оставалось обнуляемым. В конце концов, я использовал ModelForms для принудительного применения изображения на этапе проверки:
admin.py:
Похоже, это применимо только для некоторых ситуаций (конечно, когда вам нужно ввести более строгие правила в поле подкласса).
В качестве альтернативы вы можете использовать
clean_<fieldname>()
метод вместоclean()
, например, еслиtown
необходимо заполнить поле :источник
Вы не можете переопределить поля модели, но это легко достигается путем переопределения / указания метода clean (). У меня была проблема с полем электронной почты, и я хотел сделать его уникальным на уровне модели и сделал это так:
Затем сообщение об ошибке записывается в поле формы с именем «электронная почта».
источник
Мое решение так же просто, как и следующее
monkey patching
, обратите внимание, как я изменил полеmax_length
атрибута foname
вLongNamedRestaurant
модели:источник