Django 1.9: Полевые столкновения с полем несуществующего поля в родительской модели
У меня есть несколько простых моделей: Profile, Certifier и Designer, два из которых наследуются от Profile (multi table inheritance). В Designer есть внешний ключ для Certifier.
class Profile(models.Model):
TYPES = (
('admin', _('Administrator')),
('certifier', _('Certifier')),
('designer', _('Designer'))
)
user = models.OneToOneField(User)
type = models.CharField(max_length=9, choices=TYPES)
def __str__(self):
return self.user.username + ' (' + self.type + ')'
class Admin(Profile):
pass
class Certifier(Profile):
pass
class Designer(Profile):
certifier = models.ForeignKey(Certifier)
В Django 1.8 это работает отлично, но в 1.9 я получаю:
django.core.management.base.SystemCheckError: SystemCheckError: проверка системы выявила некоторые проблемы:
ОШИБКИ:
check.Designer.certifier: (models.E006) Поле "certifier" сталкивается с полем "certifier" из модели "check.profile".
(Profile.type не имеет значения в этом случае, мне просто нужно его отличить от зарегистрированных типов профилей пользователя).
check.profile, очевидно, не имеет поля 'certifier'. Это ошибка или мне что-то не хватает? То же самое происходит в другом проекте.
Ответы
Ответ 1
Я думаю, что вы не должны использовать сертификат имени для этого отношения внешнего ключа, потому что у класса Profile фактически есть поля certifier, admin и designer (хотя по дескриптору) в соответствии с docs, и в этом случае имена на самом деле будут сталкиваться.
from django.contrib.auth.models import User
c = Certifier.objects.create(
type='admin',
user=User.objects.latest('date_joined'),
)
p = c.profile_ptr
print(p.certifier) #username (admin)
Изменить на что-то вроде certifier_field = models.ForeignKey(Certifier)
Как было отмечено в комментариях, вы можете переименовать модели в CertifierProfile, AdminProfile и т.д., чтобы избежать столкновения.
Или вы также можете отключить проверку, добавив в свои настройки SILENCED_SYSTEM_CHECKS = ['models.E006'], но это нехорошо подход.
Ответ 2
Вы можете указать Profile
абстрактный класс. Это остановит проверку путаницы с родительскими полями.
class Meta:
abstract = True