如何通过Queryset获取Django中已激活Pin对应Ticket的总金额
问题:获取已激活Pin对应Ticket的总金额报错解决
我正在开发一款活动应用,需要获取已激活的Pin对应的Ticket的总金额,但编写代码后出现错误:'QuerySet' object has no attribute 'ticket'。以下是我的模型和视图代码,求正确实现方法:
模型代码
class Ticket(models.Model): event = models.ForeignKey(Event, on_delete=models.CASCADE) price = models.PositiveIntegerField() category = models.CharField(max_length=100, choices=PASS, default=None, blank=False, null=False) added_date = models.DateField(auto_now_add=True) def __str__(self): return f"{self.event} " #Prepare the url path for the Model def get_absolute_url(self): return reverse("ticket-detail", args=[str(self.id)]) def generate_pin(): return ''.join(str(randint(0, 9)) for _ in range(6)) class Pin(models.Model): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) value = models.CharField(max_length=6, default=generate_pin, blank=True) added = models.DateTimeField(auto_now_add=True, blank=False) reference = models.UUIDField(primary_key = True, editable = False, default=uuid.uuid4) status = models.CharField(max_length=30, default='Not Activated') #Save Reference Number def save(self, *args, **kwargs): self.reference == str(uuid.uuid4()) super().save(*args, **kwargs) def __unicode__(self): return self.ticket class Meta: unique_together = ["ticket", "value"] def __str__(self): return f"{self.ticket}" def get_absolute_url(self): return reverse("pin-detail", args=[str(self.id)])
原视图代码
from django.db.models import Count, Sum def profile(request): amount_sold_pins = Pin.objects.filter(status='Activated') total_sold_tickets = amount_sold_pins.ticket.price total = total_sold_tickets.aggregate(total = Sum('price')).get('total') or 0 context = { 'guest':reservations, 'total':total, } return render(request, 'user/profile.html', context)
错误原因
amount_sold_pins是Pin对象的查询集合(QuerySet),不是单个Pin实例,所以不能直接通过.ticket.price访问关联的Ticket属性。QuerySet没有ticket这个属性,这就是报错的根源。
正确实现方案
直接通过Pin的查询集,关联到Ticket的price字段进行聚合求和,修改后的视图代码如下:
from django.db.models import Sum def profile(request): # 过滤已激活的Pin,关联到Ticket的price字段求和 total = Pin.objects.filter(status='Activated').aggregate( total=Sum('ticket__price') )['total'] or 0 # 注意:原代码里的reservations变量需确保已正确定义并赋值 context = { 'guest': reservations, 'total': total, } return render(request, 'user/profile.html', context)
额外优化提示
- 模型里的
generate_pin方法:需要加上@staticmethod装饰器,否则作为默认值调用时会报错(缺少实例参数):
@staticmethod def generate_pin(): return ''.join(str(randint(0, 9)) for _ in range(6))
- Pin模型的save方法:里面的
self.reference == str(uuid.uuid4())是比较运算符,不是赋值,应改成=;另外字段定义已设置default=uuid.uuid4,这段赋值逻辑可以直接删除,避免重复生成UUID:
def save(self, *args, **kwargs): super().save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者apollos
相关产品推荐
相关产品推荐

