3

我正在使用 Django(德语-瑞典语)开发一个词汇培训计划。

该应用程序的词汇数据由大量“词汇卡”组成,每张卡都包含一个或多个德语单词或对应于一个或多个瑞典语术语的术语。

score培训仅适用于注册用户,因为该应用程序通过为每个词汇卡保存一个来跟踪用户的表现。

词汇卡有一个级别(基本、高级、专家)和分配给它们的任意数量的标签。

当注册用户开始培训时,应用程序需要计算用户对每个级别和标签的平均分数,以便他进行选择。

我通过引入一个名为的模型解决了这个问题,该模型CardByUser具有一个score和字段以及ForeignKey与模型UserCard. 现在我可以使用 Django 的聚合函数计算平均分数。

最大的缺点:只有当CardByUser数据库中当前存在的每个 Card 实例都有一个实例时,这才有效,即使用户只训练了 100 张卡片。我当前的解决方案是在创建时和用户注册时创建所有这些CardByUser实例。Card当然,这在数据库内存和计算时间方面都相当低效(注册用户需要相当长的时间)。

而且它似乎很不雅,哪一种最让我烦恼。

有一个更好的方法吗?

在计算 a 的平均分数时,也许可以告诉 Django 以下内容Card

  • 如果CardByUser给定Card和用户的 a 存在,则使用其分数。
  • 如果CardByUser不存在,请使用默认值 --> 分数 0。

这可以做到吗?如果是这样,怎么做?

编辑:澄清 感谢 S.Lott 的第一个答案,但我认为我的问题有点复杂。我的错,我试图用我的模型中的一些实际代码来澄清。

class Card(models.Model):
    entry_sv = models.CharField(max_length=200)
    entry_de = models.CharField(max_length=200)
    ... more fields ...

class CardByUser(models.Model):
    user = models.ForeignKey(User)
    card = models.ForeignKey(Card, related_name="user_cards")
    score = models.IntegerField(default=0)
    ... more fields ...

这意味着许多CardByUser对象都与单个Card.

现在在我的视图代码中,我需要创建一个CardByUser满足以下条件的对象查询集:

  • 相关Card对象的tag字段包含某个字符串(我现在这也不是最佳的,但不是我问题的重点......)
  • 用户是当前用户

然后我可以汇总分数。我当前的代码看起来像这样(缩短):

user_cards = CardByUser.objects.filter(user=current_user)
                               .filter(card__tags__contains=tag.name)
avg = user_cards_agg.aggregate(Avg('score'))['score__avg']

如果CardByUser当前用户的 a 并且Card不存在,则它根本不会被包含在聚合中。这就是为什么我创建所有CardByUser分数为 0 的 s。

那我怎么能摆脱那些呢?任何想法,将不胜感激!

4

2 回答 2

2

这就是方法(也许还有属性)的用途。

class OptionalFKWithDefault( models.Model ):
    another = models.ForeignKey( AnotherModel, blank=True, null=True )
    @property
    def another_score( self ):
        if self.another is None:
            return 0
        else:
            return self.another.score
于 2009-06-05T15:32:12.490 回答
1

这可能与您的问题并不完全相关,但看起来CardByUser确实应该是与额外字段的多对多关系。(见http://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships

也许你可以这样改变你的模型?

class Card(models.Model):
    entry_sv = models.CharField(max_length=200)
    entry_de = models.CharField(max_length=200)
    ... more fields ...
    users = models.ManyToManyField(User, through='CardByUser')

class CardByUser(models.Model):
    user = models.ForeignKey(User)
    card = models.ForeignKey(Card)
    score = models.IntegerField(default=0)

然后你不必显式地创建 CardByUser 对象,因为这一切都由 Django 处理。您还应该能够简化聚合查询:

user_cards = Card.objects.filter(users=current_user)
                         .filter(tags__contains=tag.name)
...
于 2009-06-08T11:08:48.587 回答