Django - Настраиваемый профиль пользователя - PullRequest
2 голосов
/ 09 июня 2011

Итак, у меня есть UserProfile в Django, в котором есть определенные поля, необходимые для всего проекта - день рождения, место жительства и т. Д. - и он также содержит много информации, которая на самом деле не имеет никакого значения, поскольку логика идет - родной город, обо мне и т. д. Я пытаюсь сделать свой проект более гибким и применимым к большему количеству ситуаций, чем моя собственная, и я хотел бы сделать так, чтобы администраторы экземпляра проекта могли добавлять любые поля им нравится UserProfile без непосредственного изменения модели. То есть я хотел бы, чтобы администратор нового экземпляра мог создавать новые атрибуты пользователя на лету в зависимости от его конкретных потребностей. Из-за характера ORM это возможно?

Ответы [ 2 ]

4 голосов
/ 09 июня 2011

Что ж, простое решение - создать новую модель с именем 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,]

Это позволит администратору добавить длинный список атрибутов. Ограничения заключаются в том, что вы не можете выполнять какую-либо проверку входных данных (не будучи уверенными в том, что это действительный текст), вы также ограничены атрибутами, которые можно описать простым английским языком (то есть вы не сможете выполнять много входов в них). ) и вы действительно не сможете сравнивать атрибуты между UserProfiles (без большого количества обращений к базе данных в любом случае)

0 голосов
/ 09 июня 2011

Вы можете хранить дополнительные данные в сериализованном состоянии. Это может сэкономить вам некоторые попадания в БД и немного упростить структуру вашей базы данных. Может быть лучшим вариантом, если вы планируете использовать данные только для целей отображения.

Пример реализации (не тестировался) ::

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] См. Также этот пост Джейкоба Каплана-Мосса о динамическом формировании формы. Однако это не касается проверки.

...