How to get information out of 'OneToOneField' and use this information in admin.py list_display?

I making my first site, this is my first big project so I stuck at one issue and can't solve it.. Here part of my code with error:

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}'
...

When I saving this code it sending:

par_value = gfield_playing.field_par
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'OneToOneField' object has no attribute 'field_par'

And about admin.py that sending error, when I tried some solves from internet, I actually made the 'to_par' well, and fixed 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
...

but, when I tried to add 'to_par' in admin.py list_display it gave error like <cant use 'to_par' because it is not callable> or smth like this, so after week of trying to solve it I'm here to take some help from experts.

I said what I tried above.

Define a property [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}'

In case you thus fetch the .to_par from a PlayerInstance, then it will thus run the function behind the property and return that result.


Note: Models normally have no Instance suffix. An object from a class is always called an "instance", by naming the class …Instance, one gets the impression that the variable is an instance of a class.

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