Как добавить поле 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, создается впечатление, что переменная является экземпляром класса.

Вернуться на верх