3

这是我的代码:

class Resource(models.Model):
    [...]

class Theme(models.Model):
    [...]
    resource_set = models.ManyToManyField(Resource, through='Match', related_name='theme_set', blank=True)

class Match(models.Model):
    resource = models.ForeignKey(Resource)
    theme = models.ForeignKey(Theme)
    [...]

我有意使用中间模型,因为我想为关系添加一些属性。现在...我知道在 Theme 中声明多对多关系时,我也从 Resource 获得了反向关系。看到我正在使用的related_name 了吗?这样,我在两个模型中都有“对称”字段名称(两个模型中的resource_set、theme_set 和 match_set)。

我的问题是,当我从两个模型(资源和主题)生成表单时,它们不是对称的。当我生成主题表单时,我会自动获得一个多项选择字段以从现有资源中进行选择。但是当我生成资源表单时,我不会。

所以这就是为什么我想在两个模型中声明多对多关系 - 使它们真正相等(不像在 Pizzas 和 Toppings 示例中;)并生成这些额外的多项选择字段。问题是 - 是否有可能,还是我必须自己将多项选择字段添加到 ResourceForm 或使用我还不理解的 FormSets?

顺便说一句 - 因为我无法使用 save() 从 ThemeForm 保存新主题(“无法在指定中间模型的 ManyToManyField 上设置值。”)我这样做:

[...]
theme = form.save(commit=False)
theme.save()
for resource in form.cleaned_data['resource_set']:
    match = Match()
    match.resource = resource
    match.theme = theme
    match.save()
return redirect([...]
4

1 回答 1

0

您可以简单地在两侧定义它。

一个问题是related_name - 据我所知,没有办法告诉ORM“我会自己处理反向关系”。因此,您需要更改相关名称,以免它们与真实字段名称发生冲突。在此示例中,我在related_names 中添加了下划线,因此资源对象现在同时具有theme_set 和_theme_set,它们是相同数据的两个句柄。

class Resource(models.Model):
    [...]
    theme_set = models.ManyToManyField('Theme',
        through='Match', 
        related_name='_resource_set', 
        blank=True)

class Theme(models.Model):
    [...]
    resource_set = models.ManyToManyField(Resource,
        through='Match',
        related_name='_theme_set',
        blank=True)

此外,如果您使用 South,您可能需要将_ignored_fields 添加到字段之一。

于 2013-02-23T09:36:35.060 回答