Передать дополнительные параметры сигналу post_save

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

Эти данные сохраняются в классе модели Account через post_save сигнал. Процесс создания пользователя происходит примерно так:

# Function to Create user Account/Profile
def create_user_account(sender, instance, created, **kwargs):
    if created:
      models.Account.objects.create(user=instance)

# Create User / User Registration
def UserRegistration(request):
    if request.method == 'POST':
        username = request.POST['fn'].capitalize() + ' ' + request.POST['ln'].capitalize()
        # CREATE USER
        newuser = User.objects.create_user(username=username, email=request.POST['email'], password=request.POST['pw'])
        newuser.first_name = request.POST['fn'].capitalize()
        newuser.last_name = request.POST['ln'].capitalize()
        newuser.save()
    return HttpResponse(username)

#Post Save handler to create user Account/Profile
post_save.connect(create_user_account, sender=User)

Здесь UserRegistration Функция вызывается, когда пользователь публикует форму, и с помощью этой функции я могу получить данные POST, я хочу передать эти данные в метод create_user_account, чтобы он заполнял поля в модели Account.

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

3 ответа

Решение

Что я делаю, так это устанавливаю несколько _attrs для экземпляра и затем использую их в обработчике сигналов.

Я полагаю, ваш случай может быть:

# Function to Create user Account/Profile
def create_user_account(sender, instance, created, **kwargs):
    if created:
        attrs_needed = ['_language', '_field', '_otherfield']
        if all(hasattr(instance, attr) for attr in attr_needed):
            models.Account.objects.create(
                user=instance, 
                language=instance._language, 
                field=instance._field,
                otherfield=instance._otherfield)

# Create User / User Registration
def UserRegistration(request):
  if request.method == 'POST':
    username = request.POST['fn'].capitalize() + ' ' + request.POST['ln'].capitalize()
    # CREATE USER
    newuser = User.objects.create_user(
        username=username, email=request.POST['email'],
        password=request.POST['pw'])
    newuser.first_name = request.POST['fn'].capitalize()
    newuser.last_name = request.POST['ln'].capitalize()

    # Set some extra attrs to the instance to be used in the handler.
    newuser._language = request.POST['language']
    newuser._field = request.POST['field']
    newuser._otherfield = request.POST['otherfield']
    newuser.save()


  return HttpResponse(username)

#Post Save handler to create user Account/Profile
post_save.connect(create_user_account, sender=User)

Я ненавижу это делать, и я думаю, что это может привести к поломкам ужасным образом, и иногда это трудно отладить, а также нет строгого способа принудительного получения данных, необходимых для обработчика, можно определить signal_data(data, signal, instance) определить данные, необходимые для обработчика сигнала для конкретного экземпляра.

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

До свидания.

И то и другое User.objects.create_user а также User.objects.create немедленно вызывает post_save обработчик, потому что save называется в UserManagercreate_user, Поэтому я не могу себе представить, как может сработать ответ Хорхе (по крайней мере, если вы хотите, чтобы сохранение сработало только один раз - почему вы вызвали его дважды???). Что вы хотите сделать, это посмотреть, что create_user делает, рассекать его и таким образом вы можете реально контролировать, когда save называется:

# Function to Create user Account/Profile
def create_user_account(sender, instance, created, **kwargs):
    if created:
        attrs_needed = ['_language', '_field', '_otherfield']
        if all(hasattr(instance, attr) for attr in attr_needed):
            models.Account.objects.create(
                user=instance, 
                language=instance._language, 
                field=instance._field,
                otherfield=instance._otherfield)

# Create User / User Registration
def UserRegistration(request):
  if request.method == 'POST':
    username = request.POST['fn'].capitalize() + ' ' + request.POST['ln'].capitalize()
    # CREATE USER
    newuser = User(
        username=username,
        email=request.POST['email'],
        first_name=request.POST['fn'].capitalize()
        last_name = request.POST['ln'].capitalize()
    )
    newuser.set_password(request.POST['pw'])

    # Set some extra attrs to the instance to be used in the handler.
    newuser._language = request.POST['language']
    newuser._field = request.POST['field']
    newuser._otherfield = request.POST['otherfield']
    newuser.save()  # Now this will be really the first save which is called

  return HttpResponse(username)

#Post Save handler to create user Account/Profile
post_save.connect(create_user_account, sender=User, weak=False)

Обратите внимание, что я также использую weak=False когда я подключаю обработчик.

я нашел это receiver(post_save, sender=User)вызывается сразу, когда мы используем create_userа также createметод, Итак, нам нужно сначала инициализировать объект, а затем заполнить дополнительное поле.

Другие вопросы по тегам