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)
    [...]

関係にいくつかの属性を追加したいので、意図的に中間モデルを使用しています。さて...テーマで多対多の関係を宣言するとき、私はリソースからも逆の関係を取得していることを知っています。私が使用しているrelated_nameを参照してください。このようにして、両方のモデルに「対称」フィールド名があります(両方のモデルにresource_set、theme_set、およびmatch_set)。

私の問題は、両方のモデル(リソースとテーマ)からフォームを生成するときに、それらが対称的ではないことです。テーマフォームを生成すると、既存のリソースから選択するための複数選択フィールドが自動的に取得されます。しかし、リソースフォームを生成するときは生成しません。

だから私は両方のモデルで多対多の関係を宣言したいのです-それらを本当に等しくし(ピザとトッピングの例のように;)、これらの追加の複数選択フィールドを生成させたいのです。問題は-それは可能ですか、それとも自分でResourceFormに複数選択フィールドを追加する必要がありますか、それともまだ理解していないFormSetを使用する必要がありますか?

ところで-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

両側で簡単に定義できます。

問題の 1 つは related_name です。私の知る限り、ORM に「自分で逆リレーションを処理します」と伝える方法はありません。したがって、実際のフィールド名と衝突しないように related_names を変更する必要があります。この例では、related_names にアンダースコアを追加したため、Resource オブジェクトには、同じデータへの 2 つのハンドルである 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 を使用している場合は、フィールドの 1 つにadd_ignored_fieldsが必要になる場合があります。

于 2013-02-23T09:36:35.060 に答える