Передавать дополнительные параметры для сигнала 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
.
Ответы
Ответ 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
при подключении обработчика.