1

私の質問は、関連モデルのIDではなく、関連モデルから指定されたフィールドを使用するカスタムモデルフォームを作成する方法はありますか?

明確にするために、私が次の2つのモデルを持っている場合:

class ModelOne(models.Model):
  id = models.AutoField(primary_key = True)
  name = models.CharField(unique = True, blank = False, null = False)

class ModelTwo(models.Model):
  id = models.AutoField(primary_key = True)
  parent = models.ForeignKey(ModelOne, blank = False, null = False)
  attribute_1 = models.CharField(blank = False, null = False)
  attribute_2 = models.IntegerField(blank = False, null = False)

ここで、ModelFormを使用してModelTwoでUpdateViewを作成すると、親フィールドにModelOneの対応するIDが事前に入力されます。ただし、ModelOneのname属性を表示してから、フォームの送信時に、(ModelOneの)一意の名前をModelOneの対応するインスタンスに解析します。私がこのようにしたい理由は、ユーザーの観点からは、「id」ではなくModelOneの名前(ModelTwoインスタンスを更新する場合)を処理する方がはるかに直感的であると信じているためです。

私がこれを行う方法の提案はありますか?

4

2 に答える 2

1

まず、ModelOneでunicodeメソッドを定義してみます。ソリューションには当てはまらないかもしれませんが、持つ価値はあります - フォーム選択ウィジェットでテキスト値を駆動します...

def __unicode__(self):
    '''Warning: be careful not to use related objects here,
    could cause unwanted DB hits when debugging/logging
    '''
    return self.name

それが十分でない場合は、このようなものが機能する可能性があります (プロファイルに添付されたユーザーの名前を更新するフォームから適応されます)...

class M2Form(forms.ModelForm):
    m1_name = forms.CharField()

    class Meta:
        model = ModelTwo

    def save(self, *args, **kw):
        # Update your name field here, something like
        if self.cleaned_data.get('m1_name'):
            self.instance.parent = ModelOne.objects.get(name=self.cleaned_data.get('m1_name'))
            return super(M2Form, self).save(*args, **kw)

これはテストされていないため、名前が存在することを検証し、元の親フィールドがフォームに表示されないようにするために、これを調整する必要がある可能性があります。運が良ければ、最初の答えはあなたの質問が何であるかをカバーしています。

于 2012-06-20T00:59:48.323 に答える
0

Rogの回答を出発点として使用し、Djangoの内部のいくつかを掘り下げて、最終的に実用的なソリューションにたどり着きました。私の Django の知識レベルを考えると、これを行うためのより良い方法があると思います。別の方法がある場合は、それを追加してください。

上記の 2 つのモデルに基づいて、次のフォーム クラスを作成しました。

class CustomForm(forms.ModelForm):
    parent = models.CharField(label='Name')

    class Meta:
       model = ModelTwo
       exclude = ['parent']

    def __init__(self,*args,**kwargs):
       # The line of code below is the one that I was looking for. It pre-populates 
       # the "parent" field of the form with the "name" attribute of the related 
       # ModelOne instance.
       kwargs['initial']['parent'] = kwargs['instance'].parent.name
       super(CustomForm,self).__init__(*args,**kwargs)
       # The next line is for convenience and orders the form fields in our desired 
       # order. I got this tip from: 
       # http://stackoverflow.com/questions/913589/django-forms-inheritance-and-order-of-form-fields
       self.fields.keyOrder = ['parent','attribute_1','attribute_2']

    def save(self, *args, **kwargs):
       if self.cleaned_data.get('parent'):
       # This section of code is important because we need to convert back from the 
       # unique 'name' attribute of ModelOne to the corresponding instance so that
       # ModelTwo can be saved. Thanks goes to Rog for this section of code.
           self.instance.parent = ModelOne.objects.get(name=self.cleaned_data.get('parent'))
           return super(CustomForm, self).save(*args, **kwargs)
于 2012-06-21T01:33:05.510 に答える