如何允许django最终用户以受控和安全的方式创建自己的表?
这是关于:Django/Django-ORM/POSTGRES 目标: 允许最终用户从现有模型继承、在其中创建额外字段或创建全新模型 伪模型代码 示例: 原始模型如何允许django最终用户以受控和安全的方式创建自己的表?,django,python-3.x,django-models,Django,Python 3.x,Django Models,这是关于:Django/Django-ORM/POSTGRES 目标: 允许最终用户从现有模型继承、在其中创建额外字段或创建全新模型 伪模型代码 示例: 原始模型 name = "Main Model" Value_1 = "First Value" 用户创建的变体 parent = OriginalModel name = "Custom Model" Value_1 = "First Value" Value_2 = "Custom Additional Value" 我试过: test
name = "Main Model"
Value_1 = "First Value"
用户创建的变体
parent = OriginalModel
name = "Custom Model"
Value_1 = "First Value"
Value_2 = "Custom Additional Value"
我试过:
test_choices = (
('str', 'str'),
('num', 'num'),
)
class App(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='users')
name = models.CharField(max_length=100)
class AppField(models.Model):
app = models.ForeignKey(App, on_delete=models.CASCADE)
type = models.CharField(max_length=100, choices=test_choices, null=True)
title = models.CharField(max_length=100, default='')
问题
如何允许用户创建将AppField中的字段用作模型字段的AppItem
你知道做这件事的更好方法吗?以下是我如何开始使用JSONField(和PostgreSQL)来应对这一挑战。这只是给你一个基本的想法,我试着遵循Django的原则。前两个简单的模型。一个用于存储用户定义的模型定义,另一个用于存储数据
models.py
from django.db import models
from django.contrib.postgres.fields import JSONField
from django.utils.text import slugify
class ModelDefinition(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
verbose_name = models.CharField(max_length=50)
name = models.CharField(max_length=50, unique=True)
definition = JSONField()
def save(self, *args, **kwargs):
self.name = slugify(self.verbose_name)
super().save(*args, **kwargs)
class Data(models.Model):
model_definition = models.ForeignKey(ModelDefinition, on_delete=models.CASCADE)
data = JSONField()
from .models import ModelDefinition, Data
from django.http import HttpResponse, JsonResponse
def create_model_definition(request):
''' Handles creation of model definitions '''
model_definition = {
'fields': [
{
'name': 'automobile',
'verbose_name': 'Automobile',
'data_type': 'string',
'max_length': 50,
'blank': False,
'null': False
},
{
'name': 'type',
'verbose_name': 'Automobile type',
'data_type': 'string',
'max_length': 20,
'blank': False,
'null': False
},
{
'name': 'doors',
'verbose_name': 'Number of doors',
'data_type': 'integer',
'blank': False,
'null': False
}
],
'global_options': {
'guest': {
'verbose_name': 'Allow guests to enter data',
'option': True
},
'public': {
'verbose_name': 'Data is publicly accessible',
'option': False
}
}
}
ModelDefinition.objects.create(
user=request.user,
verbose_name='My automobiles',
definition=model_definition
)
return HttpResponse('model definition created')
def add_data(request, table='my-automobiles'):
''' Handles data entry '''
model_definition = get_object_or_404(ModelDefinition, user=request.user, name=table)
if not request.user.is_authenticated and not model_definition.definition['global_options']['guest']['option']:
return HttpResponse('Sorry, only authenticated users can enter data')
data_rows = [
{
'automobile': 'Audi',
'type': 'limousine',
'doors': 4
},
{
'automobile': 'Fiat',
'type': 'hatchback',
'doors': 3
},
{
'automobile': 'Iveco',
'type': 'truck',
'doors': 2
}
]
for row in data_rows:
Data.objects.create(
model_definition=model_definition,
data=data
)
return HttpResponse('rows saved')
def show_data(request, table='my-automobiles'):
''' Returns data in JSON format '''
model_definition = get_object_or_404(ModelDefinition, name=table)
if not request.user.is_authenticated and not model_definition.definition['global_options']['public']['option']:
return HttpResponse('Sorry, only authenticated users can view data')
data = Data.objects.filter(model_definition__name=table)
return JsonResponse(data)
下面是一个如何添加模型定义、添加和返回数据的示例。我没有包括数据验证,因为编写基本验证代码至少需要一个小时
views.py
from django.db import models
from django.contrib.postgres.fields import JSONField
from django.utils.text import slugify
class ModelDefinition(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
verbose_name = models.CharField(max_length=50)
name = models.CharField(max_length=50, unique=True)
definition = JSONField()
def save(self, *args, **kwargs):
self.name = slugify(self.verbose_name)
super().save(*args, **kwargs)
class Data(models.Model):
model_definition = models.ForeignKey(ModelDefinition, on_delete=models.CASCADE)
data = JSONField()
from .models import ModelDefinition, Data
from django.http import HttpResponse, JsonResponse
def create_model_definition(request):
''' Handles creation of model definitions '''
model_definition = {
'fields': [
{
'name': 'automobile',
'verbose_name': 'Automobile',
'data_type': 'string',
'max_length': 50,
'blank': False,
'null': False
},
{
'name': 'type',
'verbose_name': 'Automobile type',
'data_type': 'string',
'max_length': 20,
'blank': False,
'null': False
},
{
'name': 'doors',
'verbose_name': 'Number of doors',
'data_type': 'integer',
'blank': False,
'null': False
}
],
'global_options': {
'guest': {
'verbose_name': 'Allow guests to enter data',
'option': True
},
'public': {
'verbose_name': 'Data is publicly accessible',
'option': False
}
}
}
ModelDefinition.objects.create(
user=request.user,
verbose_name='My automobiles',
definition=model_definition
)
return HttpResponse('model definition created')
def add_data(request, table='my-automobiles'):
''' Handles data entry '''
model_definition = get_object_or_404(ModelDefinition, user=request.user, name=table)
if not request.user.is_authenticated and not model_definition.definition['global_options']['guest']['option']:
return HttpResponse('Sorry, only authenticated users can enter data')
data_rows = [
{
'automobile': 'Audi',
'type': 'limousine',
'doors': 4
},
{
'automobile': 'Fiat',
'type': 'hatchback',
'doors': 3
},
{
'automobile': 'Iveco',
'type': 'truck',
'doors': 2
}
]
for row in data_rows:
Data.objects.create(
model_definition=model_definition,
data=data
)
return HttpResponse('rows saved')
def show_data(request, table='my-automobiles'):
''' Returns data in JSON format '''
model_definition = get_object_or_404(ModelDefinition, name=table)
if not request.user.is_authenticated and not model_definition.definition['global_options']['public']['option']:
return HttpResponse('Sorry, only authenticated users can view data')
data = Data.objects.filter(model_definition__name=table)
return JsonResponse(data)
好吧,我就是这样开始工作的,不知道我会得到什么。当然,我还没有测试过这些代码:)澄清说明:我们为什么要这样做?在应用程序[Podio]中可以找到此功能的一个很好的用途,它允许您创建和自定义自己的待办事项列表应用程序[],然后最终用户只需填写如下字段即可添加一个应用程序项目:[]想象一堆电子表格,一个独特的电子表格是一个应用程序,每一列是一个AppField,每一行都在AppItem中我很确定podio.com使用JSON来形成“用户表”(请参阅)或者具有类似功能的东西。允许用户破坏基本数据库结构是不明智的。您最终会发现一个数据库完全是一堆乱七八糟的表,其中大多数表可能已过时/未被使用。谢谢!我想这会行得通的。我要试试这个[];并将每一行存储在TestAppData表中,以便两个用户可以同时编辑两个不同的应用程序行,而无需相互重写,但我们必须在每个TestAppData项上声明列。不要在JSONField上过早放弃:)这是需要动态结构的完美选择。大致上是这样做的?@Sam,是的。来自JSON的数据字段在Django中转换为字典。