<p>我是这样做的。在</p>
<p>我需要这样做是因为我有一个模型,它将信息存储为键值对,我需要在该模型上构建一个ModelForm,但是ModelForm应该将键值对显示为字段,即将行透视到列。默认情况下,模型的<code>get()</code>方法总是返回自身的一个模型实例,我需要使用一个自定义模型。我的键值对模型是这样的:</p>
<pre><code>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()
</code></pre>
<p>我在此基础上构建了一个自定义管理器来重写<code>get()</code>方法:</p>
^{pr2}$
<p>这个管理器将实例化这个抽象模型的一个实例。(抽象模型没有表,因此Django不会抛出错误)</p>
<pre><code>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)
)
</code></pre>
<p>这个代理拥有我想要在ModelFom中显示的所有字段,并将它们作为键值对存储在模型中。现在,如果我需要添加更多字段,我可以简单地修改这个抽象模型,而不必编辑实际的模型本身。现在我有了一个模型,我可以简单地在它上面构建一个ModelForm,如下所示:</p>
<pre><code>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
</code></pre>
<p>我希望这有帮助。要想弄清楚这一点,需要对API文档进行大量挖掘。在</p>