Более одного профиля в Django? - PullRequest
0 голосов
/ 03 января 2011

Можно ли использовать функции аутентификации пользователя в Django с несколькими профилями?

В настоящее время у меня есть файл settings.py, в котором есть это:

AUTH_PROFILE_MODULE = 'auth.UserProfileA'

и модели.py файл, в котором есть это:

from django.db import models
from django.contrib.auth.models import User

class UserProfileA(models.Model):
    company = models.CharField(max_length=30)
    user = models.ForeignKey(User, unique=True)

таким образом, если пользователь входит в систему, я могу легко получить профиль, потому что у пользователя есть метод get_profile ().Тем не менее, я хотел бы добавить UserProfileB.Если немного оглянуться, то кажется, что отправной точкой является создание суперкласса для использования в качестве AUTH_PROFILE_MODULE, в котором и UserProfileA, и UserProfileB наследуют этот суперкласс.Проблема в том, что я не думаю, что метод get_profile () возвращает правильный профиль.Это возвратило бы экземпляр суперкласса.Я пришел из Java-фона (полиморфизм), поэтому я не уверен, что именно я должен делать.

Спасибо!

Редактировать:

Ну, я нашел способсделать это с помощью так называемого «хака наследования», который я нашел на этом сайте http://djangosnippets.org/snippets/1031/

Это работает очень хорошо, однако, исходя из Java-фона, где это происходит автоматически, я немного обеспокоентот факт, что кто-то должен был написать это и назвать это «хаком», чтобы сделать это на python.Есть ли причина, по которой Python не включает это?

Ответы [ 4 ]

4 голосов
/ 03 января 2011

Таким образом, проблема, с которой вы столкнетесь, заключается в том, что все, что вы хотите для своего профиля, нужно сохранить в какой-то базе данных.В основном все серверные части для django являются реляционными, и, таким образом, каждое поле в постоянном объекте присутствует в каждой строке таблицы.Есть несколько способов получить то, что вы хотите.

Django обеспечивает некоторую поддержку наследования * 1003. * Вы можете использовать перечисленные приемы и получать разумные результаты полиморфным способом.

Самый прямой подход - использовать наследование нескольких таблиц,Примерно:

class UserProfile(models.Model):
    # set settings.AUTH_PROFILE_MODULE to this class!
    pass

class UserProfileA(UserProfile):
    pass

class UserProfileB(UserProfile):
    pass

Чтобы использовать его:

try:
    profile = user.get_profile().userprofilea
    # user profile is UserProfileA
except UserProfileA.DoesNotExist:
    # user profile wasn't UserProfileB
    pass
try:
    profile = user.get_profile().userprofileb
    # user profile is UserProfileB
except UserProfileB.DoesNotExist:
    # user profile wasn't either a or b...

Редактировать: Re, ваш комментарий.

Реляционная модель подразумевает рядвещи, которые кажутся несогласными с объектно-ориентированной философией.Чтобы отношение было полезным, требуется, чтобы каждый элемент отношения имел одинаковые измерения, так что реляционные запросы действительны для всего отношения.Поскольку это известно априори, перед тем как встретить экземпляр класса, хранящийся в отношении, строка не может быть подклассом.Orm django преодолевает это несоответствие импеданса, сохраняя информацию подкласса в другом отношении (одно специфическое для подкласса). Существуют другие решения, но все они подчиняются этой основной природе реляционной модели.

Если это поможет вам с этим смириться, я бы посоветовал посмотреть, как постоянство в RDBM работает для приложений в отсутствие ORM.В частности, реляционные базы данных больше относятся к коллекциям и сводкам многих строк, чем к применению поведения к данным, извлеченным из базы данных.

Конкретный пример использования функции профиля django.contrib.auth является довольно неинтересным, особенно если единственный способ, которым когда-либо используется эта модель, - это выборка данных профиля, связанных с конкретным экземпляром django.contrib.auth.models.User.Если других запросов нет, вам вообще не нужен подкласс django.models.Model.Вы можете выбрать обычный класс Python и сохранить его в поле BLOB-объекта другой безликой модели.

С другой стороны, если вы хотите делать более интересные вещи с профилями, например, поиск пользователей, которые живут вдля определенного города, тогда для всех профилей будет важно иметь индекс для своей городской собственности.Это не имеет ничего общего с ООП, и все, что связано с реляционными.

1 голос
/ 03 января 2011

Приложение idios от команды Pinax, нацеленное на решение многопрофильной задачи. Вы можете настроить модель так, чтобы наследование базового класса профиля было абстрактным или не абстрактным. https://github.com/eldarion/idios.

0 голосов
/ 03 января 2011

Если у вас есть параметры для каждого пользователя, я бы рекомендовал поместить их в отдельную модель.

Упрощенный пример:

class UserSettings(models.Model):
    user = models.ForeignKey(User, primary_key = True)

    # Settings go here
    defaultLocale = models.CharField(max_length = 80, default = "en_US")
    ...

Это будет использоваться так:

def getUserSettings(request):
    try:
        return UserSettings.objects.get(pk = request.user)
    except UserSettings.DoesNotExist:
        # Use defaults instead, that's why you should define reasonable defaults
        # in the UserSettings model
        return UserSettings()
0 голосов
/ 03 января 2011

Вот ответ на мой вопрос о том, как заставить работать несколько профилей:

from django.contrib.contenttypes.models import ContentType
class Contact(models.Model):

    content_type = models.ForeignKey(ContentType,editable=False,null=True)

    def save(self):
        if(not self.content_type):
            self.content_type = ContentType.objects.get_for_model(self.__class__)
        self.save_base()

    def as_leaf_class(self):
        content_type = self.content_type
        model = content_type.model_class()
        if(model == Contact):
            return self
        return model.objects.get(id=self.id)

Я не очень понимаю, почему это работает или почему разработчики django / python заставили наследование работать так

...