Django:允许用户向模型添加字段

时间:2016-01-20 17:47:14

标签: python django model

我刚刚开始使用Django,并希望为应用程序创建一个模型。

我发现Djangos功能 - 根据模型中定义的字段类型自动为表单定义验证和html窗口小部件类型 - 为模型中的字段定义选择集 非常有用,我想充分利用它。另外,我想充分利用管理界面。

但是,如果我想允许应用程序的用户向模型添加字段,该怎么办?例如,考虑一本简单的地址簿。我希望用户能够在管理设置中为他的所有联系人定义其他属性,即添加传真号码字段,以便可以将传真号码添加到所有联系人。

从关系数据库的角度来看,我会有一个带有属性的表(PK:atr_ID,atr_name,atr_type)和属性与具有来自属性和联系人的外键的联系人之间的N:N关系 - 即它将导致3个表在DB中。正确?

但是我不能直接在Django模型中定义字段类型。现在这里的最佳做法是什么?如何使用Djangos功能并允许用户通过管理界面添加aditional / custom字段?

谢谢! :)

最佳

Teconomix

3 个答案:

答案 0 :(得分:1)

我建议将json作为字符串存储在数据库中,这样就可以根据需要扩展它,并且字段列表可能会很长。

编辑: 如果您正在使用其他该死的后端,则可以使用Django-jsonfield。如果您使用的是Postgres,则它具有本地jsonfield支持,用于增强查询等。

答案 1 :(得分:0)

您可以使用InlineModelAdmin个对象。它应该是这样的:

#models.py
from django.db import models

class Person(models.Model):
   name = models.CharField(max_length=100)

class ContactType(models.Model):
   name = models.CharField(max_length=100)

class Contact(models.Model):
   person = models.ForeignKey(Person, on_delete=models.CASCADE)
   contact_type = models.ForeignKey(ContactType, on_delete=models.CASCADE)
   value = models.CharField(max_length=100)

#admin.py
from django.contrib import admin

class ContactInline(admin.TabularInline):
    model = Contact

class PersonAdmin(admin.ModelAdmin):
    inlines = [
        ContactInline,
    ]

顺便说一下... stackoverflow问题应该包含一些代码。在提出问题之前,你应该尝试做点什么。

答案 2 :(得分:0)

我使用了这种方法,首先在django-payslip中看到,以允许可扩展字段。这提供了一种向模型添加字段的结构,您可以从中允许用户通过标准视图过程添加/编辑(无需管理员黑客攻击)。这应该足以让你入门,并看看django-payslip的源代码(参见视图)还提供了视图Mixins和表单作为如何呈现给用户的示例。

class YourModel(models.Model):
    extra_fields = models.ManyToManyField(
        'your_app.ExtraField',
         verbose_name=_('Extra fields'),
         blank=True, null=True,
    )


class ExtraFieldType(models.Model):
    """
    Model to create custom information holders.
    :name: Name of the attribute.
    :description: Description of the attribute.
    :model: Can be set in order to allow the use of only one model.
    :fixed_values: Can transform related exta fields into choices.
    """
    name = models.CharField(
        max_length=100,
        verbose_name=_('Name'),
    )

    description = models.CharField(
        max_length=100,
        blank=True, null=True,
        verbose_name=_('Description'),
    )

    model = models.CharField(
        max_length=10,
        choices=(
            ('YourModel', 'YourModel'),
            ('AnotherModel', 'AnotherModel'), # which models do you want to add extra fields to?
        ),
        verbose_name=_('Model'),
        blank=True, null=True,
    )

    fixed_values = models.BooleanField(
        default=False,
        verbose_name=_('Fixed values'),
    )

    class Meta:
        ordering = ['name', ]

    def __unicode__(self):
        return '{0}'.format(self.name)



class ExtraField(models.Model):
    """
    Model to create custom fields.
    :field_type: Connection to the field type.
    :value: Current value of this extra field.
    """
    field_type = models.ForeignKey(
        'your_app.ExtraFieldType',
        verbose_name=_('Field type'),
        related_name='extra_fields',
        help_text=_('Only field types with fixed values can be chosen to add'
                    ' global values.'),
    )

    value = models.CharField(
        max_length=200,
        verbose_name=_('Value'),
    )

    class Meta:
        ordering = ['field_type__name', ]

    def __unicode__(self):
        return '{0} ({1}) - {2}'.format(
            self.field_type, self.field_type.get_model_display() or 'general',
            self.value)