пользовательский класс ломает приложения в django? - PullRequest
3 голосов
/ 29 мая 2009

Допустим, я правильно подклассифицировал пользовательскую модель (CustomUser) (как объяснено здесь: http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/)

и установил приложение комментариев.

для доступа пользователя к комментарию в шаблоне, который я пишу:

{{comment.user}} # which provides User, not my CustomUser

и, следовательно,

{{comment.user.CustomProperty}} #does not work.

Как я могу обойти это?

Ответы [ 3 ]

2 голосов
/ 29 мая 2009

Как вы можете видеть в комментариях этого поста, он все еще спорно обсуждается, что это лучший способ.

Я тоже попробовал это сделать, используя подклассы, но я столкнулся со многими проблемами, в то время как с использованием профилей отлично работает для меня.

class IRCUser(models.Model):
    user        = models.ForeignKey(User, unique=True)
    name        = models.CharField(max_length=100, blank= True, null = True )
    friends     = models.ManyToManyField("IRCUser", blank= True, null = True)
    dataRecieved= models.BooleanField(default=False)

создание IRCUser работает так:

>>> IRCUser(user = User.objects.get(username='Kermit')).save()

РЕДАКТИРОВАТЬ: Почему изящные user_profiles:

Предположим, мы пишем веб-приложение, которое будет вести себя как многопротокольный чат. Пользователи могут предоставлять свои учетные записи в ICQ, MSN, Jabber, FaceBook, Google Talk .....

Мы можем создавать пользовательский класс по наследству, который будет содержать всю дополнительную информацию.

class CustomUser(User):
    irc_username = models.CharField(blank=True, null=True)
    irc_password = models.PasswordField(blank=True, null=True)
    msn_username = models.CharField(blank=True, null=True)
    msn_password = models.PasswordField(blank=True, null=True)
    fb_username = models.CharField(blank=True, null=True)
    fb_password = models.PasswordField(blank=True, null=True)
    gt_username = models.CharField(blank=True, null=True)
    gt_password = models.PasswordField(blank=True, null=True)
    ....
    ....

это приводит к

  • строки данных с большим количеством нулевых значений
  • хитрый что-если-тогда проверка
  • невозможность иметь более одного аккаунта с таким же сервисом

Так что теперь давайте сделаем это с user_profiles

class IRCProfile(models.Model):
    user = models.ForeignKey(User, unique=True, related_name='ircprofile')
    username = models.CharField()
    password = models.PasswordField()

class MSNProfile(models.Model):
    user = models.ForeignKey(User, unique=True, related_name='msnprofile')
    username = models.CharField()
    password = models.PasswordField()

class FBProfile(models.Model):
    user = models.ForeignKey(User, unique=True, related_name='fbprofile')
    username = models.CharField()
    password = models.PasswordField()

результат:

  • User_profiles может быть создан при необходимости
  • БД не затопляется нулевыми значениями
  • n профилей одного типа могут быть назначены одному пользователю
  • проверка проста

это может привести к более загадочному синтаксису в шаблонах, но мы можем использовать некоторые ярлыки в наших views / template_tags или использовать {% with ... %}, чтобы изменить его, как мы хотим.

2 голосов
/ 29 мая 2009

ForeignKey из comments.Comment относится к встроенному в Django User объекту, поэтому запрос comment.user даст вам родительский объект (то есть: базовая User модель). Однако наследование django действительно позволяет получить версию подкласса от суперкласса:

{{ comment.user.customeruser }}

Что тогда позволит вам сделать:

{{ comment.user.customeruser.customproperty }}

Мне кажется, что это слабость в реализации наследования Django, поскольку она не совсем отражает поведение, которое вы ожидаете от наследования объектов в Python в целом, но, по крайней мере, есть обходной путь. Поскольку я вряд ли спешу представить патч с моей версией правильного поведения, я не могу пожаловаться: -)


Я согласен с комментарием Карла Мейера: может потребоваться автоматическое извлечение подкласса без изменения таблицы db родительской модели, а возврат экземпляра подкласса из запроса родительского класса противоречит обещанию Джанго о том, что набор запросов возвращает модель на котором был запущен набор запросов.

Однако на практике я все еще нахожу, что наследование Джанго иногда приводит к некоторым неуклюжим дополнительным шагам. Используя Django с 0.91 и зная, что все различные стратегии для решения проблем объектно-реляционного отображения имеют компромисс, я очень рад иметь наследование в Django сейчас и чувствую, что текущая реализация превосходна ... так что я бы Ненавижу, когда мой первоначальный ответ воспринимается как незначительный по отношению к проекту.

Таким образом, я подумал, что отредактирую этот ответ, чтобы связать его с ответом, который сам Карл предоставил для решения в тех случаях, когда вы не знаете, какой тип подкласса: Как получить доступ к дочерним классам объект в Django, не зная имени дочернего класса? . Там он предлагает советы по использованию инфраструктуры ContentType. Все еще есть некоторая косвенность, но хорошая, обобщаемая опция в наборе инструментов.

1 голос
/ 29 мая 2009

Я не думаю, что есть способ обойти это, потому что, как вы сказали, comment.user - это User, а не CustomUser.

См. http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models:

ВОПРОСЫ ПОСЛЕ ВОЗВРАТА МОДЕЛИ, КОТОРЫЕ ЗАПРОСИЛИ
Django не может вернуть, скажем, объект MyUser всякий раз, когда вы запрашиваете объекты пользователя. Набор запросов для пользовательских объектов будет возвращать эти типы объектов. Весь смысл прокси-объектов заключается в том, что код, основанный на исходном Пользователе, будет их использовать, и ваш собственный код может использовать расширения, которые вы включили (что никакой другой код в любом случае не использует). Это не способ заменить пользовательскую (или любую другую) модель повсюду чем-то своим.

Может быть, в этом случае старый способ использования UserProfile будет лучшим выбором?

Извините, если я не очень помогаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...