首先,抱歉,如果这不是StackOverflow的合适问题。我试图让它尽可能普遍。
我想创建一个拥有用户的数据库(MySQL,运行Django的站点),可以为各种类型的操作分配一定数量的点 - 这是一个协作游戏。我的要求是获得:
到目前为止,这是我的Django models.py文件:
class SiteUser(models.Model):
name = models.CharField(max_length=250 )
email = models.EmailField(max_length=250 )
date_added = models.DateTimeField(auto_now_add=True)
def points_total(self):
points_added = PointsAdded.objects.filter(user=self)
points_total = 0
for point in points_added:
points_total += point.points
return points_total
class PointsAdded(models.Model):
user = models.ForeignKey('SiteUser')
action = models.ForeignKey('Action')
date_added = models.DateTimeField(auto_now_add=True)
def points(self):
points = Action.objects.filter(action=self.action)
return points
class Action(models.Model):
points = models.IntegerField()
action = models.CharField(max_length=36)
然而,我很快就清楚地知道,实际上非常复杂(至少在Django查询术语中)来计算用户的排名并返回用户的排行榜。至少,我发现它很难。有没有更优雅的方式来做这样的事情?
This question似乎暗示我甚至不应该有一个单独的积分表 - 人们怎么想?拥有单独的表会感觉更健壮,但我没有太多的数据库设计经验。
答案 0 :(得分:1)
这是旧的,但我不确定为什么你有2个单独的表(Points Added& Action)。现在已经很晚了,所以也许我的思绪没有嘀嗒,但似乎你出于某种原因将一张桌子分成了两张桌子。你似乎没有从中获得任何好处。它不像是一对多关系吗?
首先,我会将这两个表结合起来。其次,最好将points_total存储到site_user表中的值中。这就是我认为德米特里试图提到的内容,但没有明确说明。这种方式而不是做这整个额外的查询(拉动用户在他的网站历史中所做的一切都是昂贵的)+循环动作(通过它甚至更昂贵),你可以把它拉成一个字段。它正在使数据非规范化以获得更大的利益。
每次添加有点的内容时,请务必更新值。您可以使用django的post_save信号来执行此操作
答案 1 :(得分:0)
将点数保存在同一张表中要困难一些,但这完全是值得的。如果您在用户模型上计算了总点数,则可以执行非常简单的排序/过滤操作。而且只有当某些内容发生变化时才能计算总数(不是每次都要显示它们)。只需将一些验证逻辑放入post_save信号中,并确保通过测试覆盖这个逻辑并且你很好。
P.S。 wiki上的denormalization。