Запазете изчислената стойност като поле за модел

Като продължение на предишния ми въпрос имам нов. Как мога да запазя тази изчислена стойност като поле за модел. Бих искал да го използвам в моите изгледи и шаблони, за да подредя списъка по това поле.

Моите модели:

class Tournament(models.Model):
   name = models.CharField(max_length=100)
   date = models.DateTimeField('date')
   player_num = models.IntegerField(verbose_name="")
   points = models.FloatField(default=1000.00)
   def get_rating(self):
       return self.points / 1000.00

class TournamentStandings(models.Model):
   tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
   player = models.ForeignKey(Player, on_delete=models.CASCADE)
   player_place = models.FloatField(verbose_name=u"")
   player_points = models.FloatField(verbose_name="", 
   blank=True) #added for testing to save the calculated value in it
   @property 
   def get_player_points(self, obj):
       return obj.tournament.player_num * obj.tournament.get_rating() - 
       obj.tournament.get_rating()*(obj.player_place - 1.00)

   def save(self, *args, **kwargs):
       self.player_points = self.get_player_points   
       super(TournamentStandings, self).save(*args, **kwargs)



   def __float__(self):
     return self.player_points

Странно, тъй като в списъка с администратори имам колона, в която player_points се изчисляват правилно, но когато добавя нов екземпляр на модела и се опитвам да го запазя, получавам тази грешка: 'TournamentStandings' object has no attribute 'get_player_points'. Причината ли е, че се опитвам да направя „самостоятелно“ запазване и изчислението ми е (self, obj) ?? Всякакви съвети са добре дошли.


person Jan Mejor    schedule 07.12.2017    source източник


Отговори (2)


get_player_points() е метод и изисква скоби.

def save(self, *args, **kwargs):
     self.player_points = self.get_player_points() 
person Asher    schedule 08.12.2017
comment
Сега имам това: get_player_points() takes exactly 2 arguments (1 given) - person Jan Mejor; 08.12.2017
comment
да Написахте get_player_points да приема 2 аргумента: self и obj. Self се предава автоматично, но трябва да подадете валиден obj аргумент или да промените кода си, така че да не изисква втори аргумент. - person Asher; 08.12.2017
comment
Подозирам, че всъщност искате да премахнете obj като аргумент и да използвате self на всички места, където сте използвали obj в метода. return self.tournament.player_num * self.tournament.get_rating() -self.tournament.get_rating()*(self.player_place - 1.00) - person Asher; 08.12.2017
comment
Предполагам, че трябва да преработя още нещо. След като направих това, което предложихте, получих това: global name 'tournament' is not defined - person Jan Mejor; 09.12.2017
comment
Тествам повече с тази идея - ако пропусна 'obj', завършвам с неизвестни екземпляри на полето Tournament. Трябва да предам информация, която използвате 'get_rating'. - person Jan Mejor; 09.12.2017
comment
Все още търся решение на моя проблем. Успях да запазя изчислена стойност в модела на турнира. Там нямаше нужда от скоби. Мисля, че проблемът е, че имам други екземпляри на модела в моите изчисления. Ако намеря начин да ги присвоя на променлива в TournamentStandings, трябва да съм си у дома. Работен код за турнирен модел: def get_rating(self): return (self.points) / (1000.00) def save(self, *args, **kwargs): self.rating = self.get_rating super(Tournament, self).save(*args, **kwargs) - person Jan Mejor; 09.12.2017

Публикувам работещо решение на моя проблем. Няма нужда от скоби.

Първо коригирах модела на турнира, за да мога да запазя get_rating като поле:

class Tournament(models.Model):
    name = models.CharField(max_length=100)
    rating = models.FloatField(verbose_name="Rating", blank=True)

    @property
    def get_rating(self):
        return (self.points) / (1000.00)

    def save(self, *args, **kwargs):
        self.rating = self.get_rating
        super(Tournament, self).save(*args, **kwargs)

    def __float__(self):
        return self.rating

Когато имах това, се опитах да го копирам на втори модел. Проблемът беше, че не можах да го накарам да работи поради свързан obj, който извиквах в изчислението си. Но! Успях да присвоя тези стойности на променливи в get_player_points и сега всичко работи по предназначение:

class TournamentStandings(models.Model):
    tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
    player = models.ForeignKey(Player, on_delete=models.CASCADE)
    player_place = models.FloatField(verbose_name="")
    player_points = models.FloatField(verbose_name="", blank=True)

    @property
    def get_player_points(self):
        player_num = float(self.tournament.player_num)
        rating = float(self.tournament.rating)
        player_points = float(rating*player_num-rating*(self.player_place - 1.00))
        return player_points

    def save(self, *args, **kwargs):
        self.player_points = self.get_player_points
        super(TournamentStandings, self).save(*args, **kwargs)

    def __float__(self):
        return self.player_points

И това работи! Всякакви мисли за подобрения, които мога да направя, са добре дошли.

person Jan Mejor    schedule 18.12.2017