繁体   English   中英

Django模型:如果不存在外键关系,如何返回默认值?

[英]Django models: how to return a default value in case of a non-existing foreign-key relationship?

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

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

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

词汇卡具有级别(基本,高级,专家)以及分配给它们的任意数量的标签。

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

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

最大的缺点:只有当DB中当前存在的每个Card实例都有CardByUser实例时, CardByUser ,即使用户只训练了100张卡。 我目前的解决方案是在创建Card时以及用户注册时创建所有CardByUser实例。 当然,就数据库存储器和计算时间而言,这都是相当无效的(注册用户需要相当长的时间)。

它似乎相当不优雅,哪种错误最让我烦恼。

有一个更好的方法吗?

也许在计算Card的平均分数时可以告诉Django:

  • 如果存在给定Card和用户的CardByUser ,请使用其分数。
  • 如果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对象的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']

如果当前用户和CardCardByUser不存在,则它将不会包含在聚合中。 这就是我用0分创建所有CardByUser的原因。

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

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

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

这可能与您的问题并不完全相关,但看起来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)
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM