#python #django #django-models #django-forms #django-views
#python #django #django-модели #django-forms #django-просмотры
Вопрос:
Я использую расширенную версию UserCreationForm для добавления пользователей через мой собственный шаблон, который работает хорошо.
Я также хотел бы включить, как часть того же шаблона формы, настраиваемое поле из моей модели userprofile, чтобы при создании пользователя также создавался профиль пользователя с моим настраиваемым полем.
Мой подход к этому заключался в использовании двух форм и объединении их в одном шаблоне с помощью одной кнопки отправки.
Форма отображается точно так, как я хотел, и корректно возвращает ошибки проверки, но, как и следовало ожидать, она падает, когда дело доходит до сохранения в базе данных. Когда я вызываю save() в форме пользователя, пользователь создается, но, конечно, когда я пытаюсь сохранить форму userprofile, она выдает ошибку, потому что пользователь еще не существует, поэтому с ним не связан пользователь.
Хотя я думаю, что понимаю причину моей проблемы, я в недоумении относительно того, как это исправить, я даже не уверен, правильный ли подход, который я выбрал.
Я включил весь свой код ниже, включая модель, а также формы и представление, на всякий случай, если это поможет кому-либо лучше понять, что я пытаюсь сделать:
Класс UserProfile (models.py )
LEVEL = (
('admin', 'administrator'),
('team', 'team leader'),
('member', 'team member'),
)
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
level = models.CharField(choices=LEVEL, max_length=20)
Классы UserCreationForm и UserProfileForm (forms.py )
class UserCreationFormExtended(UserCreationForm):
def __init__(self, *args, **kwargs):
super(UserCreationFormExtended, self).__init__(*args, **kwargs)
self.fields['first_name'].required = True
self.fields['last_name'].required = True
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name')
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.fields["level"].choices = ( ('admin', 'administrator'), ('team', 'team leader'), ('member', 'team member') )
class Meta:
model = UserProfile
представление use_add (views.py )
def user_add(request):
if request.method == 'POST':
uform = UserCreationFormExtended(request.POST)
pform = UserProfileForm(request.POST)
if uform.is_valid():
uform.save()
pform.save()
return render_to_response('user/add_success.html', context_instance=RequestContext(request))
else:
return render_to_response('user/add.html', { 'uform' : uform, 'pform' : pform }, context_instance=RequestContext(request))
else:
uform = UserCreationFormExtended()
pform = UserProfileForm()
return render_to_response('user/add.html', { 'uform' : uform, 'pform' : pform }, context_instance=RequestContext(request))
Ответ №1:
Сначала добавьте exclude = ('user',)
в мета-класс для profileForm. Тогда, на ваш взгляд:
user_valid = uform.is_valid()
profile_valid = pform.is_valid()
if user_valid and profile_valid:
user = uform.save()
profile = pform.save(commit=False)
profile.user = user
profile.save()
Хотя мне приходит в голову, что, поскольку у вас есть только одно поле в форме профиля, более простой способ сделать это — полностью забыть эту форму и просто добавить поле в пользовательскую форму:
class UserCreationFormExtended(UserCreationForm):
level = forms.ChoiceField(choices=LEVEL, max_length=20)
... etc...
if uform.is_valid():
user = uform.save()
profile = Profile.objects.create(user=user, level=uform.cleaned_data['level']))
Комментарии:
1. Спасибо! Я смотрел на это так долго, что не мог видеть дерево для деревьев.
Ответ №2:
Здесь я нашел аналогичное решение: http://sontek.net/blog/detail/extending-the-django-user-model
По сути, вы просто расширяете форму UserCreationForm по умолчанию, но сохраняете то же имя. Делая это таким образом, вам не нужно добавлять какие-либо новые представления или что-то в этом роде, это работает без проблем с тем, как документы Django говорят вам делать профили пользователей.
Честно говоря, я не понимаю, почему они объясняют, как добавить поля на страницу администратора, а затем не говорят вам, как на самом деле использовать эти поля где угодно.