将表单字段存储为键值对/单独行
我在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
)
当表单提交时,我该如何把表单字段存储为键值对?然后在页面渲染时,如何用这些键的值来初始化表单?我试着找过相关的实现,但一直没找到。
有没有人能帮帮我?
谢谢。
2 个回答
1
我猜你是想把'theme'当作名字,把它的值存起来,'defaultinputmessage'也是同样的意思。如果是这样的话,下面的代码应该可以用:
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])
0
这是我怎么做的。
我之所以这样做,是因为我有一个模型,它以键值对的形式存储信息。我需要在这个模型上构建一个模型表单(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)
)
这个代理模型包含了我希望在模型表单中显示的所有字段,并且在我的模型中以键值对的形式存储。现在,如果我需要添加更多字段,我只需修改这个抽象模型,而不必去编辑实际的模型本身。现在我有了一个模型,我可以简单地在它上面构建一个模型表单,如下所示:
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文档。