Как позволить конечному пользователю django создавать свои собственные таблицы контролируемым и безопасным способом? - PullRequest
0 голосов
/ 29 декабря 2018

Это касается: Django / Django ORM / POSTGRES

Цель: Разрешить конечному пользователю наследовать от существующей модели, создать в ней дополнительные поля или создание совершенно новой модели.

код псевдо-модели Пример:

OriginalModel

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='')

Задача Как разрешить пользователю создавать AppItem, который использует поля в AppField в качестве полей модели?

Знаете ли вы лучший способ сделать все это?

1 Ответ

0 голосов
/ 29 декабря 2018

Вот как я бы начал решать эту проблему с использованием JSONField (и PostgreSQL).Это просто чтобы дать вам основную идею, и я попытался следовать принципам Джанго.Первые две простые модели.Один для хранения определений моделей, как определено пользователями, а другой для хранения данных.

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)

Так вот, как бы я начал работать над этим, не знаю, чем я в итоге закончу.Конечно, я не проверял ни один из этого кода:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...