首页 > 解决方案 > 我为用户在 django 中为送货员实施了星级评分系统,但我被困在如何计算平均值上

问题描述

我有一个模型名称 Ratings 并通过外键关系连接到自定义用户模型。我使用 javascript 发布数据并通过使用 id 的 get 方法在后端获取评级但问题是评级过程工作正常但它只是升级当前查询集曾经被视为送货员得到评级。那么我如何计算平均值,因为它不存储以前的查询集,而只是升级该特定送货员的查询集

视图.py

def rate_user(request):
if request.method == 'POST':
    el_id = request.POST.get('el_id')
    val = request.POST.get('val')
    print(val)
    obj = Ratings.objects.get(id=el_id)
    obj.rated_number = val
    obj.save()
    return JsonResponse({'success':'true', 'score': val}, safe=False)
return JsonResponse({'success':'false'})

模型.py

class Ratings(models.Model):
    rated_user = models.ForeignKey(User,on_delete=models.CASCADE,blank=True,null=True)
    avg_rating = models.CharField(max_length=5,null=True,blank=True,default=0)
    # count = models.CharField(max_length=100000,blank=True,null=True,default=0)
    rated_number = models.IntegerField(blank=True,null=True,default=0,
        validators = [
             MaxValueValidator(5),
             MinValueValidator(1),
        ]
   )
    
    def __str__(self):
        return str(self.pk)
    
@receiver(post_save, sender=User)
def create_ratings(sender, instance, created, **kwargs):
    if created:
        if instance.is_delivery_man or instance.is_driver:
            Ratings.objects.create(rated_user=instance)

js

<script>
    const one = document.getElementById('first')
    const two = document.getElementById('second')
    const three = document.getElementById('third')
    const four = document.getElementById('fourth')
    const five = document.getElementById('fifth')

    // get the form, confirm-box and csrf token
    const form = document.querySelector('.rate-form')
    const confirmBox = document.getElementById('confirm-box')
    const csrf = document.getElementsByName('csrfmiddlewaretoken')

    const handleStarSelect = (size) => {
        const children = form.children
        console.log(children[0])
        for (let i = 0; i < children.length; i++) {
            if (i <= size) {
                children[i].classList.add('checked')
            } else {
                children[i].classList.remove('checked')
            }
        }
    }

    const handleSelect = (selection) => {
        switch (selection) {
            case 'first': {
                handleStarSelect(1)
                return
            }
            case 'second': {
                handleStarSelect(2)
                return
            }
            case 'third': {
                handleStarSelect(3)
                return
            }
            case 'fourth': {
                handleStarSelect(4)
                return
            }
            case 'fifth': {
                handleStarSelect(5)
                return
            }
            default: {
                handleStarSelect(0)
            }
        }

    }

    const getNumericValue = (stringValue) => {
        let numericValue;
        if (stringValue === 'first') {
            numericValue = 1
        }
        else if (stringValue === 'second') {
            numericValue = 2
        }
        else if (stringValue === 'third') {
            numericValue = 3
        }
        else if (stringValue === 'fourth') {
            numericValue = 4
        }
        else if (stringValue === 'fifth') {
            numericValue = 5
        }
        else {
            numericValue = 0
        }
        return numericValue
    }

    if (one) {
        const arr = [one, two, three, four, five]

        arr.forEach(item => item.addEventListener('mouseover', (event) => {
            handleSelect(event.target.id)
        }))

        arr.forEach(item => item.addEventListener('click', (event) => {
            // value of the rating not numeric
            const val = event.target.id

            let isSubmit = false
            form.addEventListener('submit', e => {
                e.preventDefault()
                if (isSubmit) {
                    return
                }
                isSubmit = true
                // rate id
                const id = e.target.id
                // value of the rating translated into numeric
                const val_num = getNumericValue(val)

                $.ajax({
                    type: 'POST',
                    url: '/rate/',
                    data: {
                        'csrfmiddlewaretoken': csrf[0].value,
                        'el_id': id,
                        'val': val_num,
                    },
                    success: function (response) {
                        console.log(response)
                        confirmBox.innerHTML = `<h1>Successfully rated with ${response.score} star</h1>`
                    },
                    error: function (error) {
                        console.log(error)
                        confirmBox.innerHTML = '<h1>Ups... something went wrong</h1>'
                    }
                })
            })
        }))
    }
</script>

形式

    {%for i in ratings%}
    <a href="#" >Average Ratings: {{i.rated_number}}</a><br><br>
    i class="fas fa-vote-yea"></i> Rate this user <br>
     <form class="rate-form" action="" method="POST" id={{i.id}}>
    {% csrf_token %}
   <button type="submit" class="fa fa-star fa-3x my-btn" id="first"></button>
   <button type="submit" class="fa fa-star fa-3x my-btn" id="second"></button>
   <button type="submit" class="fa fa-star fa-3x my-btn" id="third"></button>
   <button type="submit" class="fa fa-star fa-3x my-btn" id="fourth"></button>
   <button type="submit" class="fa fa-star fa-3x my-btn" id="fifth"></button>
   </form>
   {%endfor%}
    <br>
    <div id="confirm-box"></div>
   </div>

标签: django

解决方案


最后等待stackoverflow的答案我累了,开始调试自己,我最终得到了一个很好的数学算法来实现我想要的目标,我认为我已经实现了它,除了它不显示或取小数点后的值。avg 带有圆形。

我只是在我的模型中更改了一个字段来存储以前和现在所有的评级号码添加

class Ratings(models.Model):

rated_user = models.ForeignKey(User,on_delete=models.CASCADE,blank=True,null=True)
storing_prev_now_rated_value = models.IntegerField(null=True,blank=True,default=1)
avg_rating = models.IntegerField(null=True,blank=True,default=1)
count = models.IntegerField(blank=True,null=True)
rated_number = models.IntegerField(blank=True,null=True,default=1,
    validators = [
        MaxValueValidator(5),
        MinValueValidator(1),
    ]
)

def __str__(self):
    return self.rated_user.username

我的views.py也有变化

def rate_user(request):
if request.method == 'POST':
    el_id = request.POST.get('el_id')
    val = request.POST.get('val')
    print(val)
    obj = Ratings.objects.get(id=el_id)

    storing_prev_rated_number = obj.rated_number

    obj.rated_number = val

    obj.count = obj.count + 1
    store_count = obj.count
    old_addition_values = obj.storing_prev_now_rated_value

    obj.storing_prev_now_rated_value = int(old_addition_values) + int(val)

    store_storing_prev_now_rated_value = obj.storing_prev_now_rated_value
    print(store_storing_prev_now_rated_value)

    obj.avg_rating = float(store_storing_prev_now_rated_value // store_count)

    j  = obj.avg_rating
    print(j)
    obj.save()
    return JsonResponse({'success':'true', 'rated_number': val}, safe=False)
return JsonResponse({'success':'false'})

推荐阅读