Django管理员中的伪表单,用于在保存时生成一个json对象 [英] Pseudo-form in Django admin that generates a json object on save

查看:72
本文介绍了Django管理员中的伪表单,用于在保存时生成一个json对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有一个json对象的字段的模型。该对象在站点上用于控制一些css变量,其中包括。



现在在管理员中,我有一个文本字段,用户可以保存一个json对象。我想显示一个具有所有属性的表单,保存后,将生成一个json对象。



基本上,用户看到,数据被存储,像这样:

  {
name:hookedonwinter,
user-id 123,
basics:{
height:150,
weight:150
}
}

我宁愿让用户看到这个:

 名称:< input field> 
用户ID:< input field>
高度:< input field>
重量:< input field>

,数据仍然存储在json中。



任何指导都不胜感激。链接到文档解释这一点,双重赞赏。



谢谢!

解决方案

想法



基本上您需要做的是将JSON转换为字段。


  1. 为存储的模型创建字段JSON数据。

  2. 创建表单字段

  3. 创建小工具:


    1. 将字段渲染为多个输入

    2. 从POST / GET获取数据并将其转换回JSON


  4. <您还可以通过覆盖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.

    1. Create field for your model that stores JSON data.
    2. Create form field
    3. Create widget that:

      1. Renders fields as multiple inputs
      2. Takes data from POST/GET and transforms it back into JSON

    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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆