Django管理员中的伪表单,用于在保存时生成一个json对象 [英] Pseudo-form in Django admin that generates a json object on save
问题描述
现在在管理员中,我有一个文本字段,用户可以保存一个json对象。我想显示一个具有所有属性的表单,保存后,将生成一个json对象。
基本上,用户看到,数据被存储,像这样:
{
name:hookedonwinter,
user-id 123,
basics:{
height:150,
weight:150
}
}
我宁愿让用户看到这个:
名称:< input field>
用户ID:< input field>
高度:< input field>
重量:< input field>
,数据仍然存储在json中。
任何指导都不胜感激。链接到文档解释这一点,双重赞赏。
谢谢!
想法
基本上您需要做的是将JSON转换为字段。
- 为存储的模型创建字段JSON数据。
- 创建表单字段
- 创建小工具:
- 将字段渲染为多个输入
- 从POST / GET获取数据并将其转换回JSON
- 小部件: https://docs.djangoproject.com/en/1.3/ref/forms/widgets/
- Django代码,供参考如何创建小部件: https://code.djangoproject.com/browser/django/trunk/djan go / forms / widgets.py
- Create field for your model that stores JSON data.
- Create form field
- Create widget that:
- Renders fields as multiple inputs
- Takes data from POST/GET and transforms it back into JSON
- Widgets: https://docs.djangoproject.com/en/1.3/ref/forms/widgets/
- Django code for reference how to create widgets: https://code.djangoproject.com/browser/django/trunk/django/forms/widgets.py
<您还可以通过覆盖TextField的小部件来跳过第1步。
文档链接
概念证明
我尝试编写这个解决方案,这里的解决方案对我没有任何边缘的情况。
fields.py
import json
from django.db import models
from django import forms
from django import utils
from django.utils.translation import ugettext_lazy as _
class JSONEditableField(models.Field):
description = _(JSON)
def formfield(self,** kwargs):
defaults = {'form_class':JSONEditableFormField}
defaults.update(kwargs)
返回超级(JSONEditableField,self)。 formfield(** defaults)
class JSONEditableWidget(forms.Widget):
def as_field(self,name,key,value):
渲染键,值为字段
attrs = self.build_attrs(name =%s __%s%(name,key))
attrs ['value'] = utils.encodi ng.force_unicode(value)
return u'%s:< input%s />'%(key,forms.util.flatatt(attrs))
def to_fields ,name,json_obj):
获取json对象的渲染字段列表
inputs = []
用于键,json_obj.items()中的值:
如果(str,unicode,int)中的类型(值):
inputs.append(self.as_field(name,key,value))
elif type(value)in(dict,):
inputs.extend(self.to_fields(%s __%s%(name,key),value))
返回输入
def value_from_datadict(self,数据,文件,名称):
从POST或GET获取值并转换回JSON ..
基本上这是做所有数据变量
以fieldname__开头,并将
fieldname__key__key = value转换为json [key] [key] = value
TODO:clean语法?
TODO:整数值不需要作为字符串存储
json_obj = {}
separator =__
键,value.items()中的值:
如果key.startswith(name + separator):
dict_key = key [len(name + separator):]。split(separator)
prev_dict = json_obj
在dict_key [: - 1]中的k:
如果prev_dict.has_key(k):
prev_dict = prev_dict [k]
else:
prev_dict [k] = {}
prev_dict = prev_dict [k]
prev_dict [dict_key [-1:] [0]] = value
return json.dumps(prev_dict)
def render(self,name,value,attrs = None):
#TODO:handle empty value(render text field ?)
如果值为无或值==':
value ='{}'
json_obj = json.loads(value)
inputs = self.to_fields(name,json_obj)
#render json以及
inputs.append(value)
return utils.safestring.mark_safe(u< br />\".join(inputs))
类JSONEditableFormField(forms.Field):
widget = JSONEditableWidget
models.py
from django.db import models
from .fields import JSONEditableField
class Foo(models.Model):
text = models。 TextField()
json = JSONEditableField()
希望这有帮助, :
I have a model with a field for a json object. This object is used on the site to control some css variables, among other things.
Right now in the admin, I have a text field where a user can save a json object. I'd like to show a form with all the attributes that, upon saving, will generate a json object.
Basically, the user sees, and the data is stored, like this:
{
"name":"hookedonwinter",
"user-id":123,
"basics":{
"height":150,
"weight":150
}
}
And I'd rather have the user see this:
Name: <input field>
User Id: <input field>
Height: <input field>
Weight: <input field>
and the data still be stored in json.
Any guidance would be appreciated. Links to docs that explain this, doubly appreciated.
Thanks!
Idea
Basically what you need to do is render your JSON into fields.
You can also skip steps 1, 2 by overriding widget for TextField.
Documentation links
Proof of concept
I tried coding this solution and here is solution that worked for me without some edge cases.
fields.py
import json
from django.db import models
from django import forms
from django import utils
from django.utils.translation import ugettext_lazy as _
class JSONEditableField(models.Field):
description = _("JSON")
def formfield(self, **kwargs):
defaults = {'form_class': JSONEditableFormField}
defaults.update(kwargs)
return super(JSONEditableField, self).formfield(**defaults)
class JSONEditableWidget(forms.Widget):
def as_field(self, name, key, value):
""" Render key, value as field """
attrs = self.build_attrs(name="%s__%s" % (name, key))
attrs['value'] = utils.encoding.force_unicode(value)
return u'%s: <input%s />' % (key, forms.util.flatatt(attrs))
def to_fields(self, name, json_obj):
"""Get list of rendered fields for json object"""
inputs = []
for key, value in json_obj.items():
if type(value) in (str, unicode, int):
inputs.append(self.as_field(name, key, value))
elif type(value) in (dict,):
inputs.extend(self.to_fields("%s__%s" % (name, key), value))
return inputs
def value_from_datadict(self, data, files, name):
"""
Take values from POST or GET and convert back to JSON..
Basically what this does is it takes all data variables
that starts with fieldname__ and converts
fieldname__key__key = value into json[key][key] = value
TODO: cleaner syntax?
TODO: integer values don't need to be stored as string
"""
json_obj = {}
separator = "__"
for key, value in data.items():
if key.startswith(name+separator):
dict_key = key[len(name+separator):].split(separator)
prev_dict = json_obj
for k in dict_key[:-1]:
if prev_dict.has_key(k):
prev_dict = prev_dict[k]
else:
prev_dict[k] = {}
prev_dict = prev_dict[k]
prev_dict[dict_key[-1:][0]] = value
return json.dumps(prev_dict)
def render(self, name, value, attrs=None):
# TODO: handle empty value (render text field?)
if value is None or value == '':
value = '{}'
json_obj = json.loads(value)
inputs = self.to_fields(name, json_obj)
# render json as well
inputs.append(value)
return utils.safestring.mark_safe(u"<br />".join(inputs))
class JSONEditableFormField(forms.Field):
widget = JSONEditableWidget
models.py
from django.db import models
from .fields import JSONEditableField
class Foo(models.Model):
text = models.TextField()
json = JSONEditableField()
Hope this helps and here is how it looks:
这篇关于Django管理员中的伪表单,用于在保存时生成一个json对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!