2017-10-22 13 views
0

私はDjangoでpost_saveシグナルを使用する方法を学んでいます。私は何の誤りもないが、私がやりたいことはうまくいかない。別のモデルを保存した後、あるモデルのフィールドを自動的に更新する[Django 1.11] [Python3.x]

レビューモデルの評価を集計して平均化するモデル(モデル)があり、その数値を「average_rating」というフィールドに保存しています。

ユーザーが「レビュー」モデルで評価を提供し、平均評価が「モデル」モデルで自動的に計算され、更新されると、平均化が行われることを望みます。

私はpost_save信号でこれを行うことができます。しかし、私はどのように確かではありません。

私は何をしようとしていますか?

ありがとうございます。

models.py

from django.db import models 
from django.db.models import Func, Avg 
from django.urls import reverse 
from django.template.defaultfilters import slugify 
from django.db.models.signals import post_save 
from django.dispatch import receiver 

class Model(models.Model): 
    name = models.CharField(max_length=55, default='') 
    slug = models.SlugField(unique=True) 
    average_rating = models.DecimalField(decimal_places=1, 
              max_digits=2, 
              default=0.0, 
              blank=True, 
              null=True) 

    def __str__(self): 
     return self.name 

    def save(self, *args, **kwargs): 
     self.average_rating = self.review_set.aggregate(
        rounded_avg_rating=Round(Avg('rating')))['rounded_avg_rating'] 
     self.slug = (slugify(self.name)) 
     super(Model, self).save(*args, **kwargs) 


class Review(models.Model): 
    RATING_CHOICES = [ 
     (1, '1'), 
     (2, '2'), 
     (3, '3'), 
     (4, '4'), 
     (5, '5'), 
    ] 
    model = models.ForeignKey(Model, 
           null=True) 
    rating = models.IntegerField(choices=RATING_CHOICES, 
            default=1) 
    review_date = models.DateField(auto_now_add=True) 
    reviewer = models.ForeignKey(User, 
            null=True, 
            related_name = 'review_user') 
    comment = models.TextField(default='') 

    class Meta: 
     verbose_name_plural = 'Reviews' 
     verbose_name = 'Review' 

    def __str__(self): 
     return self.model.name 

@receiver(post_save, sender=Review) 
def update_average_rating(sender, instance, **kwargs): 
    instance.average_rating = Review.objects.aggregate(
       rounded_avg_rating=Round(Avg('rating')))['rounded_avg_rating'] 

更新:)(保存:今、私はこのエラーになっています

class Review(models.Model): 
    .... 

    def save(self, *args, **kwargs): 
     Model.save(avg_rating_flag=True) 
     super(Review, self).save(*args, **kwargs) 

:TypeError例外を

RajKrisが提供するソリューションを使用して、私はこれを得ました欠けている1つの位置的な引数: '自己'

RajKrisの更新された回答は私のproblを修正しましたem。魅力のように動作します。ここで起こるレビューオブジェクトは、対応するモデルオブジェクトを作成するたびに、新しい平均格付けで更新されます、ということです何

def save(self, *args, **kwargs): 
    super(Review, self).save(*args, **kwargs) 
    model_obj = self.model 
    model_obj.average_rating = model_obj.review_set.aggregate(
       rounded_avg_rating=Round(Avg('rating')))['rounded_avg_rating'] 
    model_obj.save() 

:あなたのレビューで

def save(self, *args, **kwargs): 
    super(Review, self).save(*args, **kwargs) 
    model_obj = self.model 
    model_obj.average_rating = model_ob.review_set.aggregate(
       rounded_avg_rating=Round(Avg('rating')))['rounded_avg_rating'] 
    model_obj.save() 

答えて

1

は、機能を保存します。

+0

応答ありがとう、RajKris。私はModelで保存することをやりたかったのですが、average_ratingフィールドを更新する前に管理者に戻ってモデルを保存する必要がありました。そのため、Reviewでモデルを更新するためにpost_save信号を使用しています。私は自動更新が必要です、または私は元に戻って保存する必要があります。レビューから新しい評価を自動的に更新する方法を教えていただけたら、Model.saveでそれを行うのは嬉しいことです。 – user2901792

+0

あなたがしなければならないことは、Reviewモデルの保存を行うことです。それは理にかなっていますか?新しいReviewオブジェクトが作成されると、この集計が実行され、モデルに保存されます。 – rajkris

+0

私は自分の答えを編集しました。それを確認してください。 – rajkris

関連する問題