Передать дополнительные параметры сигналу 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
называется в 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
когда я подключаю обработчик.
я нашел это
receiver(post_save, sender=User)
вызывается сразу, когда мы используем
create_user
а также
create
метод, Итак, нам нужно сначала инициализировать объект, а затем заполнить дополнительное поле.