使用django模型表单编辑json字段

项目详细描述

django entangled

使用标准django表单编辑json模型字段。

Build Status PyPI PyPI version PyPI Twitter Follow

用例

django模型可以包含接受存储为json的任意数据的字段。Django本身提供了 JSON field特定于Postgres。 对于其他数据库实现,有很多选择。

从模型创建表单时,与json字段关联的输入字段通常是<textarea ...><textarea>。 这个textarea小部件对于编辑来说非常实用,因为它只包含了 对象表示法。一种可能是使用泛型JSON editor, 它使用一些javascript,将小部件转换为属性值对编辑器。然而,这种方法可以防止 我们无法利用django表单框架提供的所有优秀特性,例如字段验证、规范化 数据和外键的使用。通过使用django纠缠,可以使用djangoModelForm,并存储所有, 或者关联模型中一个或多个json字段中的表单字段的子集。

安装

只需安装这个django应用程序,例如通过调用:

pip install django-entangled

不需要向项目的settings.py添加任何配置指令。

示例

比方说,我们有一个django模型来描述一堆不同的产品。有些字段被所有产品使用,而 其他人则描述了这种产品的特性。因为我们不想为每个 产品类型,我们使用json字段来存储这些任意属性。

from django.db import models
from django.contrib.postgres.fields import JSONField

class Product(models.Model):
    name = models.CharField(max_length=50)

    price = models.DecimalField(max_digits=5, decimal_places=2)
    
    properties = JSONField()

在典型的表单编辑视图中,我们将创建一个从 ModelForm并使用 类中的model属性。这里,properties字段将显示为非结构化json呈现 在一个<textarea ...><textarea>里面。这绝对不是我们想要的!相反,我们使用 特殊混合类^ {< CD8> }。

from django.contrib.auth import get_user_model
from django.forms import fields, models
from entangled.forms import EntangledModelForm
from .models import Product

class ProductForm(EntangledModelForm):
    color = fields.RegexField(
        regex=r'^#[0-9a-f]{6}$',
    )

    size = fields.ChoiceField(
        choices=[('s', "small"), ('m', "medium"), ('l', "large"), ('xl', "extra large")],
    )

    tenant = models.ModelChoiceField(
        queryset=get_user_model().objects.filter(is_staff=True),
    )

    class Meta:
        model = Product
        entangled_fields = {'properties': ['color', 'size', 'tenant']}  # fields provided by this form
        untangled_fields = ['name', 'price']  # these fields are provided by the Product model

除了MIXIN类^ {< CD8>},我们还添加了一个特殊的字典,名为{{CD10}} Meta-选项。在这个字典中,键(这里是'properties')引用模型Product中的json字段。 值(这里['color', 'size', 'tenant'])是一个命名表单字段列表,在我们的表单或基类中声明 因此。这允许我们将所有标准django表单字段赋给django中声明的任意json字段。 模型。此外,我们甚至可以使用ModelChoiceField来引用使用 generic relation

因为在这个表单中,我们还想从django模型访问非json字段,所以我们添加了一个名为 untangled_fields到我们的Meta-选项。在这个列表中,(这里['name', 'price'])我们指的是非json字段 在我们的模型中。从这两个迭代器,^ {< CD10> }和^ {CD16> },MIXIN类 EntangledModelFormMixin然后构建Meta-选项fields,否则是必需的。因此没有必要 显式声明此列表。

我们可以在任何django详细视图中使用此表单。一个典型的用例是内置的django modeladmin:

from django.contrib import admin
from .models import Product
from .forms import ProductForm

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    form = ProductForm

因为这个ModelAdmin类使用的表单 can not be created dynamically, 我们必须使用form属性显式地声明它。这是唯一必须执行的更改,在 以便在json模型字段中存储任意内容。

注意事项

由于JSON的属性,索引和因此基于字段内容构建过滤器或排序规则不是 简单,与标准模型字段相同。因此,如果主要关注的是存储数据, 而不是挖掘数据。

外键存储为json字段中的"fieldname": {"model": "appname.modelname", "pk": 1234},这意味着 我们没有数据库限制。如果删除了目标对象,则该外键指向任何地方。因此总是 请记住,我们没有任何引用完整性,因此必须以防御的方式编写代码。

更改

  • 0.3

    • 添加支持对于ModelMultipleChoiceField
    • 修复方法:在合并之前对entangled_fieldsuntangled_fields进行深度复制。
    • 添加Covenience类EntangledModelForm
    • 将数据从纠缠场移到其压缩表示上,现在在 在表单执行了自己的clean()之后,访问表单字段就更自然了。
    • 添加函数get_related_objectget_related_queryset,以从 json表示。
  • 0.2

    • 引入Meta-选项untangled_fields,因为0.1中的方法并不总是有效的。
    • 出于可移植性的考虑,使用formfield()方法处理django的postgres json字段。
  • 0.1

    • 初次发布。

最新Python第三方库