2011-01-03 2 views
0

Возможно ли использовать функции аутентификации пользователя Django с более чем одним профилем?Больше одного профиля в Django?

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

AUTH_PROFILE_MODULE = 'auth.UserProfileA' 

и models.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) 

таким образом, если пользователь logs in, я могу легко получить профиль, потому что у пользователя есть метод get_profile(). Однако я хотел бы добавить UserProfileB. От взгляда вокруг немного кажется, что отправной точкой является создание суперкласса, используемого в качестве AUTH_PROFILE_MODULE, и наследуемый от этого суперкласса наследует как UserProfileA, так и UserProfileB. Проблема в том, что я не думаю, что метод get_profile() возвращает правильный профиль. Он вернет экземпляр суперкласса. Я исхожу из фона java (полиморфизм), поэтому я не уверен точно, что я должен делать.

Спасибо!

Edit:

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

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

ответ

0

Вот ответ на мой вопрос о том, как получить несколько профилей для работы:

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) 

Я не понимаю, почему это работает и почему разработчики Джанго/питон из наследования работает таким образом

+0

У меня такая же проблема. Мне просто интересно, что вы поместили свой 'AUTH_PROFILE_MODULE' как? – Modelesq

4

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

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

Самый прямой подход - использовать множественное наследование таблиц. Грубо говоря:

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... 

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

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

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

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

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

+0

Это, кажется, нарушают много принципов программирования. Я предпочел бы использовать метод с djangosnippets.com, который я разместил ссылку в редактировании на мой исходный вопрос. Однако я ценю помощь. После прочтения этой ссылки, которую вы отправили по наследованию, кажется, что django не может автоматически знать, что такое дочерний класс. – JPC

1

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

0

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

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

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()