2011-06-09 38 views
2

所以我在Django中有一個UserProfile,它具有整個項目所需的某些字段 - 生日,居所等 - 並且它還包含很多實際上沒有任何信息的信息至於邏輯的重要性 - 家鄉,關於我等等。我試圖讓我的項目更靈活一些,適用於比我自己更多的情況,我想讓項目的管理員可以將他們喜歡的任何字段添加到UserProfile中,而無需直接修改模型。也就是說,我希望新實例的管理員能夠基於其特定需求即時創建用戶的新屬性。由於ORM的性質,這可能嗎?Django - 可自定義的UserProfile

+0

我寧願讓'key:value'對另一個表,其中'key'描述它是什麼類型的屬性(網站,地址)和'value'就像是「google.com」,「Mountain View」等並將這些對與'UserProfile'關聯起來。 – 2011-06-09 15:58:51

回答

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時,你會得到那個python字典。

我想,你也可以寫一個自定義字段來處理這個問題。


UPDATE(根據您的評論):

這樣看來,這裏的實際問題是如何自動創建和驗證用戶配置文件的形式。 (無論你是否使用序列化選項或複雜數據結構,它都會保留。)

既然你可以創建動態表單而沒有太大麻煩[1],那麼主要的問題是如何驗證它們。

想一想...管理員必須爲每個自定義字段指定驗證器(或字段類型),對吧?所以,你需要某種配置選項,比如說中,

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

然後,當你初始化的形式,你與他們的驗證依據此設置定義字段。

[1]另見Jacob Kaplan-Moss的this post動態表單生成。但它並不涉及驗證。

+0

我實際上已經使用JSON編寫了這個系統,這是一個巨大的痛苦如果你想隨着模型中的數據自動創建表單,特別是如果你想要正確的驗證器。根據additional_info中的內容創建動態增長的表單是絕對有可能的,但獲得驗證的表單字段要困難得多。我不會說不可能的,但我只是不知道一種方式。 – NSU 2011-06-09 17:48:28

+1

非常感謝你們的更新,當我離開這次會議時,我會給你一個機會。 – NSU 2011-06-09 18:11:26

4

一個簡單的解決方案是創建一個名爲UserAttribute的新模型,該模型具有一個鍵和一個值,並將其鏈接到UserProfile。然後你可以在django-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,] 

這將允許管理員添加一長串屬性。限制是你不能對輸入做任何驗證(除了確保它是有效的文本外),你也僅限於可以用純英文描述的屬性(即,你將無法對它們執行很多登錄),並且您無法真正能夠比較用戶配置文件之間的屬性(無論如何沒有大量數據庫點擊)

+1

+1同意,這是[數據庫規範化](http://en.wikipedia.org/wiki/Database_normalization)問題不是Django ORM。 – 2011-06-09 16:00:21

+0

是的,我在stackoverflow的其他地方看過這個建議,雖然它工作的很好,但如果我想要做的只是存儲字符串值,那麼它會崩潰,如果你想擁有一個帶有適當驗證的電子郵件字段,或者一個日期時間字段。 – NSU 2011-06-09 18:07:46

+0

然後你正在談論動態表單域。我其實只是在convore上提出一個關於這個問題,因爲我自己在想這個問題:https://convore.com/django-community/dynamic-formsform-b​​uilding/ – 2011-06-09 18:34:31