【问题标题】:How to allow a django end-user to create their own table in a controlled and secured way?如何允许 django 最终用户以受控和安全的方式创建自己的表?
【发布时间】:2019-05-27 01:29:33
【问题描述】:

这是关于: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_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?

你知道做这件事的更好方法吗?

【问题讨论】:

  • 澄清评论:我们为什么要这样做?可以在应用程序[Podio][podio.com/]中找到它的一个很好的用途允许您创建和自定义自己的待办事项列表应用程序 [i.stack.imgur.com/kcPjC.png]然后最终用户可以通过填写如下字段来简单地添加 app_item:[i.stack.imgur.com/Te4s6.png] 想象一下一堆电子表格,一个唯一的电子表格是一个App,每一列是一个AppField,每一行都在AppItem中
  • 我很确定 podio.com 使用 JSON 来形成“用户表”(参见 JSONField)或具有类似功能的东西。允许用户弄乱基本的数据库结构是不明智的。您最终会得到一个完全混乱的数据库,其中包含数千个甚至数百万个表,其中大多数可能已经过时/未使用。

标签: django python-3.x django-models


【解决方案1】:

以下是我开始使用 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()

以下是如何添加模型定义、添加和返回数据的示例。我没有包括数据验证,因为我至少需要一个小时来编写基本验证的代码。

views.py

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)

嗯,这就是我开始工作的方式,不知道我最终会得到什么。当然,我还没有测试过这段代码:)

【讨论】:

  • 谢谢!我想这会起作用我要试试这个[pastebin.com/bQnsSLEg];并将每一行存储在 TestAppData 表中,以便 2 个用户可以同时编辑 2 个不同的 App 行而不会相互覆盖,但我们必须在每个 TestAppData 项上声明列
  • 不要太早放弃 JSONField :) 它是需要动态结构的完美选择。
  • @Sam,是的。 JSONField 中的数据在 Django 中被转换为字典。
猜你喜欢
  • 2014-01-28
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 2013-07-22
  • 2013-06-02
  • 1970-01-01
相关资源
最近更新 更多