Как получить информацию из 'OneToOneField' и использовать ее в admin.py list_display?

Я делаю свой первый сайт, это мой первый большой проект, поэтому я застрял на одной проблеме и не могу ее решить. Вот часть моего кода с ошибкой:

models.py

...
class GField(models.Model):
    golf_club_name = models.CharField(
        primary_key=True,
        max_length=100,
        help_text='Enter a golf club (Gfield) name',

    )
    golf_field_par = models.PositiveIntegerField()
    def __str__(self):
        return f'{self.golf_club_name}'
class PlayerInstance(models.Model):
...
    golf_field_playing = models.OneToOneField(GField, default = 'for_nothoing',on_delete=models.RESTRICT, help_text='where is it taking part?')
    now_at_hole = models.IntegerField()
    today = models.IntegerField()
    R1 = models.IntegerField()
    R2 = models.IntegerField()
    R3 = models.IntegerField()
    R4 = models.IntegerField()
    R5 = models.IntegerField()
    all_rounds = [R1, R2, R3, R4, R5]
    counter = sum(1 for value in all_rounds if value != 0)
    par_value = gfield_playing.golf_field_par
    total = sum(all_rounds[:counter])
    if par_value * counter <= total:
        to_par = f'+{total - par_value * counter}'
    if par_value*counter>total:
        to_par = f'-{par_value * counter - total}'
...

Когда я сохраняю этот код, он отправляет:

par_value = gfield_playing.field_par
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: у объекта 'OneToOneField' нет атрибута 'field_par'

А насчет admin.py, который отправляет ошибку, когда я попробовал несколько решений из интернета, я действительно сделал 'to_par' хорошо, и исправил Error:

models.py

...
    R2 = models.IntegerField()
    R3 = models.IntegerField()
    R4 = models.IntegerField()
    R5 = models.IntegerField()
    def calculate_to_par(self):
        all_rounds = [self.R1, self.R2, self.R3, self.R4, self.R5]
        counter = sum(1 for value in all_rounds if value != 0)
        par_value = self.golf_field_playing.golf_field_par
        total = sum(all_rounds[:counter])
        if par_value * counter <= total:
            self.to_par = f'+{total - par_value * counter}'
        if par_value*counter>total:
            self.to_par = f'-{par_value * counter - total}'
        return self.to_par
...

но, когда я попытался добавить 'to_par' в admin.py list_display, он выдал ошибку типа <cant use 'to_par' because it is not callable> или что-то вроде этого, так что после недели попыток решить эту проблему я здесь, чтобы принять некоторую помощь от экспертов.

Я сказал то, что пробовал выше.

Определите свойство [python-doc]:

class PlayerInstance(models.Model):
    # …
    golf_field_playing = models.OneToOneField(
        GField,
        default='for_nothoing',
        on_delete=models.RESTRICT,
        help_text='where is it taking part?',
    )
    now_at_hole = models.IntegerField()
    today = models.IntegerField()
    R1 = models.IntegerField()
    R2 = models.IntegerField()
    R3 = models.IntegerField()
    R4 = models.IntegerField()
    R5 = models.IntegerField()

    @property
    def to_par(self):
        all_rounds = [self.R1, self.R2, self.R3, self.R4, self.R5]
        counter = sum(1 for value in all_rounds if value != 0)
        par_value = self.gfield_playing.golf_field_par
        total = sum(all_rounds[:counter])
        if par_value * counter <= total:
            return f'+{total - par_value * counter}'
        else:
            return f'-{par_value * counter - total}'

Если вы таким образом получаете .to_par из PlayerInstance, то это приведет к запуску функции, стоящей за свойством, и возвращению результата.


Примечание: Модели обычно не имеют суффикса Instance. Объект из класса всегда называется «экземпляр», называя класс …Instance, создается впечатление, что переменная является экземпляром класса.

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