Django - 可自定义的UserProfile

时间:2011-06-09 15:28:42

标签: django database-design user-profile

所以我在Django中有一个UserProfile,它包含整个项目所需的某些字段 - 生日,住所等等 - 它还包含很多实际上没有任何重要性的信息。逻辑去 - 故乡,关于我,等等。我正在努力使我的项目更灵活,适用于比我自己更多的情况,我想做到这样,项目实例的管理员可以添加任何字段他们喜欢UserProfile而无需直接修改模型。也就是说,我希望新实例的管理员能够根据用户的特定需求动态创建新属性。由于ORM的性质,这可能吗?

2 个答案:

答案 0 :(得分:4)

一个简单的解决方案是创建一个名为UserAttribute的新模型,该模型具有键和值,并将其链接到UserProfile。然后你可以在django-admin中使用它作为内联。这将允许您根据需要向UserProfile添加任意数量的新属性,所有这些都通过admin:

<强> models.py

class UserAttribute(models.Model):
    key = models.CharField(max_length=100, help_text="i.e. Age, Name etc")
    value = models.TextField(max_length=1000)
    profile = models.ForeignKey(UserProfile)

<强> admin.py

class UserAttributeInline(admin.StackedInline):
    model = UserAttribute

class UserProfile(admin.ModelAdmin):
    inlines = [UserAttibuteInline,]

这将允许管理员添加一长串属性。限制是您无法对输入进行任何验证(在确保它是有效文本之外),您也仅限于可以用简单英语描述的属性(即,您将无法对它们执行大量登录)你将无法真正比​​较UserProfiles之间的属性(无论如何没有很多数据库命中)

答案 1 :(得分:0)

您可以将其他数据存储在序列化状态。这可以节省一些数据库命中并简化数据库结构。如果您打算仅将数据用于显示目的,则可能是最佳选择。

示例实现(未测试)::

import yaml
from django.db import models

class UserProfile(models.Model):
    user = models.OneToOneField('auth.User', related_name='profile')
    _additional_info = models.TextField(default="", blank=True)

    @property
    def additional_info(self):
        return yaml.load(self._additional_info)
    @additional_info.setter
    def additional_info(self, user_info_dict):
        self._additional_info = yaml.dump(user_info_dict)

当您分配给profile.additional_info时,比如字典,它会被序列化并存储在_additional_info中(不要忘记稍后保存该实例)。然后,当您访问additional_info时,您将获得该python字典。

我想,你也可以写一个自定义字段来处理这个问题。


更新(根据您的评论):

所以看来这里的实际问题是如何自动创建和验证用户配置文件的表单。 (无论您使用的是序列化选项还是复杂的数据结构,它仍然存在。)

既然你可以毫无困难地创建动态表单[1],那么主要的问题是如何验证它们。

考虑一下......无论如何,管理员必须为每个自定义字段指定验证器(或字段类型),对吧?所以你需要某种配置选项 - 比如说,

CUSTOM_PROFILE_FIELDS = (
    {
        'name': 'user_ip',
        'validators': ['django.core.validators.validate_ipv4_address'],
        },
    )

然后,当您初始化表单时,您可以根据此设置使用验证程序定义字段。

[1]另见Jacob Kaplan-Moss关于动态表格生成的this post。但它并不涉及验证。