Django - 可定制的用户配置文件

发布于 2024-11-14 20:37:48 字数 224 浏览 3 评论 0原文

因此,我在 Django 中有一个 UserProfile,其中包含整个项目所需的某些字段 - 生日、居住地等 - 并且它还包含大量就逻辑而言实际上并不重要的信息 -家乡,关于我,等等。我试图让我的项目比我自己的项目更灵活并且适用于更多情况,并且我想让项目实例的管理员可以添加他们喜欢的任何字段用户配置文件,而无需直接修改模型。也就是说,我希望新实例的管理员能够根据用户的特定需求动态创建用户的新属性。由于 ORM 的性质,这可能吗?

So I've got a UserProfile in Django that has certain fields that are required by the entire project - birthday, residence, etc. - and it also contains a lot of information that doesn't actually have any importance as far as logic goes - hometown, about me, etc. I'm trying to make my project a bit more flexible and applicable to more situations than my own, and I'd like to make it so that administrators of a project instance can add any fields they like to a UserProfile without having to directly modify the model. That is, I'd like an administrator of a new instance to be able to create new attributes of a user on the fly based on their specific needs. Due to the nature of the ORM, is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

世态炎凉 2024-11-21 20:37:48

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

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,]

这将允许管理员添加长长的属性列表。限制是您无法对输入进行任何验证(除了确保它是有效文本之外),您还仅限于可以用简单英语描述的属性(即您将无法对它们执行太多登录)并且您将无法真正比​​较用户配置文件之间的属性(无论如何没有大量数据库命中)

Well a simple solution is to create a new model called UserAttribute that has a key and a value, and link it to the UserProfile. Then you can use it as an inline in the django-admin. This would allow you to add as many new attributes to a UserProfile as you like, all through the 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,]

This would allow an administrator to add a long list of attributes. The limitations are that you cant's do any validation on the input(outside of making sure that it's valid text), you are also limited to attributes that can be described in plain english (i.e. you won't be able to perform much login on them) and you won't really be able to compare attributes between UserProfiles (without a lot of Database hits anyway)

旧城空念 2024-11-21 20:37:48

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

示例实现(未测试)::

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 关于动态表单生成的这篇文章。但它不涉及验证。

You can store additional data in serialized state. This can save you some DB hits and simplify your database structure a bit. May be the best option if you plan to use the data just for display purposes.

Example implementation (not tested)::

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)

When you assign to profile.additional_info, say, a dictionary, it gets serialized and stored in _additional_info instead (don't forget to save the instance later). And then, when you access additional_info, you get that python dictionary.

I guess, you can also write a custom field to deal with this.


UPDATE (based on your comment):

So it appears that the actual problem here is how to automatically create and validate forms for user profiles. (It remains regardless on whether you go with serialized options or complex data structure.)

And since you can create dynamic forms without much trouble[1], then the main question is how to validate them.

Thinking about it... Administrator will have to specify validators (or field type) for each custom field anyway, right? So you'll need some kind of a configuration option—say,

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

And then, when you're initializing the form, you define fields with their validators according to this setting.

[1] See also this post by Jacob Kaplan-Moss on dynamic form generation. It doesn't deal with validation, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文