可扩展字段,使django应用程序能够将其数据存储在您的模型上。
django-appdata的Python项目详细描述
可扩展字段和相关工具,使django应用程序能够扩展 可重复使用的应用程序。
动机
在使用可重用的django应用程序时,我们经常发现需要添加
应用程序提供的模型或窗体之外的内容。一些应用试图解决
通过提供灵活的模型定义和可插入的形式(参见
django.contrib.comments
以这种方法为例)但即使如此
导致一些重复的努力。
django-appdata
app尝试通过AppDataField
、MultiForm
和AppDataModelAdmin
,
提供一个标准化的方法来扩展现有的应用程序。
支持的版本
Python:2.7,3.4,3.5,3.6 django:1.8、1.9、1.10、1.11、2.0、2.1
升级到0.2
如果要从0.1.x版本升级,请注意0.2中的以下不兼容更改
- 放弃了django<;1.8和python 2.6/3.3的兼容性
- 已放弃对
ModelAdmin.declared_fieldsets
属性的支持,请使用ModelAdmin.get_fieldsets
方法,如文档所示 低于
扩展模型
当您有一个可扩展的django应用程序时,使用AppDataField
:
from django.db import models from app_data import AppDataField class BlogPost(models.Model): text = models.TextField() app_data = AppDataField()
您的代码可以在任何(或所有)的AppDataField
上注册命名空间并存储
它通过注册一个container(的子类
AppDataContainer
)。要定义使用django的表单框架的数据:
from django.forms.models import ModelMultipleChoiceField from app_data import app_registry, AppDataForm, AppDataContainer from .models import Tag class TaggingAppDataForm(AppDataForm): public_tags = ModelMultipleChoiceField(Tag.objects.all()) admin_tags = ModelMultipleChoiceField(Tag.objects.all()) class TaggingAppDataContainer(AppDataContainer): form_class = TaggingAppDataForm def tag_string(self): print ', '.join(t.name for t in self.public_tags) app_registry.register('tagging', TaggingAppDataContainer)
这将允许您访问任何定义的AppDataField
中的'tagging'
命名空间:
from blog_app.models import BlogPost bp = BlogPost() assert bp.app_data.tagging.tag_string() == ""
其他选项
注意,如果不需要向容器添加自定义方法,可以 只需使用工厂创建子类:
app_registry.register('tagging', AppDataContainer.from_form(TaggingAppDataForm))
此外,您还可以将注册限制为给定的型号:
from blog_app.models import BlogPost app_registry.register('tagging', TaggingAppDataContainer, BlogPost)
扩展窗体
django-appdata
为django的ModelForm
提供了一个MultiForm
类-a包装。
与注册在
模型的AppDataField
,通常可扩展应用程序将创建并使用
MultiForm
而不是常规的ModelForm
:
from app_data.forms import multiform_factory from .models import BlogPost BlogPostMultiForm = multiform_factory(BlogPost)
当使用该应用程序时,任何项目都可以在该应用程序中添加其他子表单MultiForm
:
from blog_app.forms import BlogPostMultiForm BlogPostMultiForm.add_form('tagging', {'fields': ['public_tags']})
这样当可重用应用程序的代码可以保持不变并且我们可以注入 对其处理的附加形式逻辑。
其他选项
传递任何参数和关键字参数时都不会更改
ModelForm
类MultiForm
正在包装,因此即使您有自定义参数
对于您的ModelForm
一切都将继续工作:
from django.forms.models import BaseModelForm class ModelFormWithUser(ModelForm): def __init__(self, user, *args, **kwargs): self.user = user super(ModelFormWithUser, self).__init__(*args, **kwargs) BlogPostMultiForm = multiform_factory(BlogPost, form=ModelFormWithUser)
当然,您不限于使用工厂功能:
from app_data import MultiForm class MyMultiForm(MultiForm): ModelForm = BlogPostModelForm
管理中的多种格式
如果您想将自己的代码添加到管理界面,只需使用
AppDataModelAdmin
:
from django.contrib import admin from app_data.admin import AppDataModelAdmin from blog_app.models import BlogPost class BlogPostAdmin(AppDataModelAdmin): # due to the behavior of django admin validation we need to use # get_fieldsets instead of just fieldsets def get_fieldsets(self, request, obj=None): return [ (None, {'fields': ['text', ]}), ('Tagging', {'fields': [('tagging.public_tags', 'tagging.admin_tags')]}) ] admin.site.register(BlogPost, BlogPostAdmin)
其他选项
与django的管理和表单一样,您可以通过
使用AppDataModelAdmin
的multiform
属性。
幕后
django-appdata
使用TextField
在使用json的模型上存储数据
以及django的表单框架,用于数据的(反)序列化和验证。
当访问字段中的容器时,我们将尝试查找
注册表中的相应容器。如果找不到任何数据,则
如果存在则返回(dict)。为确保一切正常工作,我们建议
为您的项目放置某种类型的init代码,以确保
在运行任何实际代码之前完成注册。我们正在使用一个模块
在我们的应用程序中调用register
,然后调用类似于管理员的piece of code
自动发现以遍历已安装的应用程序并加载此模块。