Как добавить поле OneToOneField в BD на сайте Admin, который был создан с помощью функции setattr
У меня есть несколько классов в models.py, и после добавления еще одного мне нужно добавить еще один атрибут в уже созданный класс, я нашел в интернете, что лучший способ сделать это - использовать функцию setattr()
, так что я сделал все и... Это вроде работает, никаких ошибок, это отображается в админке как <django.db.models.fields.related.OneToOneField>
, но нет никакого способа выбрать его, когда я пытаюсь создать или изменить это поле, нет, это ошибка или я делаю что-то неправильно?
Вот мой код:
class PlayerInstance(models.Model):
#...
class Competition(models.Model):
#...
setattr(PlayerInstance, 'choice_to_competition', models.OneToOneField(
Competition,
default = 'for_nothoing',
on_delete=models.RESTRICT,
help_text='which competition is it taking part?',
))
И нет, я не забыл добавить 'choice_to_competition' в list_display. Вот 2 фотографии админского сайта: Я сделал их, но не могу добавить их сюда, не могу понять причину, но это не очень нужно.
Я нашел в интернете, что лучший способ сделать это - использовать функцию
setattr()
, поэтому я сделал все and.
Нет. Для «обычных» классов это может сработать. Но в Django Model
есть продвинутая мета-логика, то есть атрибуты, не переданные при построении класса, могут оказаться не в модели.
Нужно использовать метод .contribute_to_class(…)
, например:
models.OneToOneField(
Competition,
default='for_nothoing',
on_delete=models.RESTRICT,
help_text='which competition is it taking part?',
).contribute_to_class(PlayerInstance, 'choice_to_competition')
But, you don't need to do this trick to refer to a model not yet created. Indeed, for a ForeignKey
[Django-doc], OneToOneField
model field [Django-doc] and ManyToManyField
model field [Django-doc], you can use a string literal to refer to a model that has not yet been defined, with:
class PlayerInstance(models.Model):
choice_to_competition = models.OneToOneField(
'app_name.Competition',
default='for_nothoing',
on_delete=models.RESTRICT,
help_text='which competition is it taking part?',
)
# …
class Competition(models.Model):
# …
Если модель имеет одинаковый ярлык приложения, можно даже отказаться от app_label
:
class PlayerInstance(models.Model):
choice_to_competition = models.OneToOneField(
'Competition',
default='for_nothoing',
on_delete=models.RESTRICT,
help_text='which competition is it taking part?',
)
# …
class Competition(models.Model):
# …
Примечание: Модели обычно не имеют суффикса
Instance
. Объект из класса всегда называется «экземпляр», называя класс…Instance
, создается впечатление, что переменная является экземпляром класса.