Подтвердить что ты не робот

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

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

Эти данные сохраняются в классе модели учетной записи через сигнал 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.

4b9b3361

Ответ 1

Я делаю это, чтобы установить экземпляр некоторого "_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) to определить данные, необходимые для обработчика сигнала для конкретного экземпляра.

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

Bye.

Ответ 2

Оба User.objects.create_user и User.objects.create немедленно запускают обработчик post_save, потому что save вызывается в UserManager create_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 при подключении обработчика.