0

私はDjangoに次のような単純なフォームを持っています:

class SettingForm(forms.Form):
    theme = forms.CharField(rrequired=True,
        initial='multgi'
    )
    defaultinputmessage = forms.CharField(required=True,
        initial='Type here to begin..'
    )

...そしてそれを保存するモデルは次のようになります:

class Setting(models.Model):
    name = models.CharField(
        null=False, max_length=255
    )
    value= models.CharField(
        null=False, max_length=255
    )

フォームが送信されたときに、フォームフィールドをキーと値のペアとして保存し、ページがレンダリングされたときに、キーの値でフォームを初期化するにはどうすればよいですか。これの実装を探してみましたが、見つかりませんでした。

何か助けはありますか?

ありがとう。

4

2 に答える 2

1

defaultinputmessageの場合と同じように、名前として「theme」を、値としてvalueを格納することを想定しています。その場合、これは機能するはずです。

form = SettingForm({'theme': 'sometheme', 'defaultinputmessage': 'hello'})
if form.is_valid():
    for key in form.fields.keys():
        setting = Setting.objects.create(name=key, value=form.cleaned_data[key])
于 2011-09-07T19:08:17.470 に答える
0

これが私がそれをした方法です。

情報をキーと値のペアとして格納するモデルがあり、そのモデル上にModelFormを構築する必要があったため、これを行う必要がありましたが、ModelFormはキーと値のペアをフィールドとして表示する必要があります。つまり、行を列にピボットします。デフォルトでget()は、モデルのメソッドは常にそれ自体のモデルインスタンスを返すため、カスタムモデルを使用する必要がありました。キーと値のペアモデルは次のようになりました。

class Setting(models.Model):
    domain = models.ForeignKey(Domain)
    name = models.CharField(null=False, max_length=255)
    value = models.CharField(null=False, max_length=255)

    objects = SettingManager()

get()メソッドをオーバーライドするために、これに基づいてカスタムマネージャーを作成しました。

class SettingManager(models.Manager):

    def get(self, *args, **kwargs):
        from modules.customer.proxies import *
        from modules.customer.models import *

        object = type('DomainSettings', (SettingProxy,), {'__module__' : 'modules.customer'})()
        for pair in self.filter(*args, **kwargs): setattr(object, pair.name, pair.value)

        setattr(object, 'domain', Domain.objects.get(id=int(kwargs['domain__exact'])))
        return object

このマネージャーは、この抽象モデルのインスタンスをインスタンス化します。(抽象モデルにはテーブルがないため、Djangoはエラーをスローしません)

class SettingProxy(models.Model):

    domain = models.ForeignKey(Domain, null=False, verbose_name="Domain")
    theme = models.CharField(null=False, default='mytheme', max_length=16)
    message = models.CharField(null=False, default='Waddup', max_length=64)

    class Meta:
        abstract = True

    def __init__(self, *args, **kwargs):
        super(SettingProxy, self).__init__(*args, **kwargs)
        for field in self._meta.fields:
            if isinstance(field, models.AutoField):
                del field

    def save(self, *args, **kwargs):
        with transaction.commit_on_success():
            Setting.objects.filter(domain=self.domain).delete()

            for field in self._meta.fields:
                if isinstance(field, models.ForeignKey) or isinstance(field, models.AutoField):
                    continue
                else:
                    print field.name + ': ' + field.value_to_string(self)
                    Setting.objects.create(domain=self.domain,
                        name=field.name, value=field.value_to_string(self)
                    )

このプロキシには、ModelFomに表示し、モデルにキーと値のペアとして保存するすべてのフィールドがあります。これで、フィールドを追加する必要がある場合は、この抽象モデルを変更するだけで、実際のモデル自体を編集する必要がなくなります。モデルができたので、次のようにModelFormを作成できます。

class SettingsForm(forms.ModelForm):

    class Meta:
        model = SettingProxy
        exclude = ('domain',)

    def save(self, domain, *args, **kwargs):
        print self.cleaned_data
        commit = kwargs.get('commit', True)
        kwargs['commit'] = False
        setting = super(SettingsForm, self).save(*args, **kwargs)
        setting.domain = domain
        if commit:
            setting.save()
        return setting

これがお役に立てば幸いです。これを理解するには、APIドキュメントを詳しく調べる必要がありました。

于 2011-09-14T11:10:12.337 に答える