Django: UserProfile с уникальным внешним ключом в Django Admin - PullRequest
10 голосов
/ 11 мая 2010

Я расширил пользовательскую модель Django, используя пользовательский профиль с именем UserExtension. Он связан с пользователем через уникальные отношения ForeignKey, что позволяет мне редактировать его в админке в виде встроенной формы! Я использую сигнал для создания нового профиля для каждого нового пользователя:

def create_user_profile(sender, instance, created, **kwargs):  
    if created:
        try:  
            profile, created = UserExtension.objects.get_or_create(user=instance)
        except:
            pass  

post_save.connect(create_user_profile, sender=User) 

(как описано здесь, например: Расширение модели User с помощью пользовательских полей в Django ) Проблема в том, что, если я создаю нового пользователя через администратора, я получаю IntegritiyError при сохранении «столбец user_id не уникален». Не похоже, что сигнал вызывается дважды, но я думаю, что администратор пытается сохранить профиль ПОСЛЕ? Но мне нужно создание через сигнал, если я создаю нового пользователя в других частях системы!

1 Ответ

15 голосов
/ 11 мая 2010

Впоследствии django создает экземпляр администратора, поскольку сохранение всегда состоит из чего-то вроде этого:

  1. Создать объект User
  2. Создать объект профиля (не может быть раньше, потому что он указывает на пользователя).

При сохранении объекта User ORM django не может знать, что объект создания профиля последует за ним, поэтому он не будет задерживать сигнал post_save никоим образом (даже не имеет смысла).

Лучший способ справиться с этим (imho), если вы хотите сохранить сигнал post_save, это переопределить метод сохранения UserExtension примерно так:

def save(self, *args, **kwargs):
    try:
        existing = UserExtension.objects.get(user=self.user)
        self.id = existing.id #force update instead of insert
    except UserExtension.DoesNotExist:
        pass 
    models.Model.save(self, *args, **kwargs)

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

...