Сохранить рассчитанное значение как поле модели

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

Мои модели:

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'. Это потому, что я пытаюсь сделать «самостоятельное» сохранение, и мой расчет (я, объект) ?? Любые подсказки приветствуются.


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
Все еще ищу решение своей проблемы. Мне удалось сохранить рассчитанное значение в модели Tournament. Там скобки не нужны были. Я действительно думаю, что проблема в том, что в моих расчетах есть другие экземпляры модели. Если я найду способ назначить их переменной в TournamentStandings, я буду дома. Рабочий код для модели Tournament: 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

Выкладываю рабочее решение моей проблемы. Не нужно скобок.

Сначала я исправил модель Tournament, поэтому я мог сохранить 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

Когда у меня было это, я попытался скопировать его на вторую модель. Проблема заключалась в том, что я не мог заставить его работать из-за связанного объекта, который я вызывал в своем расчете. Но! Мне удалось присвоить эти значения переменным внутри 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