Django: невозможно сохранить нового пользователя
Я пытаюсь построить представление, которое показывает форму для создания нового пользователя.
Далее следуют шаблон, который я использую, urls.py и попытки кода в views.py и forms.py.
user_form.html
<form action="{% url 'app:register' %}" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Register">
</form>
urls.py
urlpatterns = [
...
path('newuser/',views.NewUser.as_view(), name='newuser'),
...
]
Первая попытка:
views.py
class NewUser(generic.CreateView):
model = User
fields = ['username','email','password']
template_name = 'app/user_form.html'
success_url = reverse_lazy('register')
Этот не вернул ошибок, но не смог сохранить новые данные пользователя.
Во второй попытке была создана форма для этого случая:
forms.py
class NewUserForm(forms.Form):
username = forms.CharField(max_length=100)
email = forms.EmailField()
password = forms.PasswordInput()
views.py
class NewUser(generic.CreateView):
model = User
form_class = NewUserForm
template_name = 'app/user_form.html'
success_url = reverse_lazy('register')
Этот вернул ошибку: TypeError at /newuser/ BaseForm.__init__() got an unexpected keyword argument 'instance'
Третья:
forms.py
class NewUserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username','email','password']
views.py
class NewUser(generic.CreateView):
model = User
form_class = NewUserForm
template_name = 'app/user_form.html'
success_url = reverse_lazy('cadastro')
Также не удается сохранить новый экземпляр User.
Я также заметил, что строка model = User в этой последней попытке может быть удалена.
Я использую запрос User.objects.all() в терминале и на странице администратора для проверки новых пользователей.
Что я не делаю?
когда вы используете CreateView на модели, он вызывает метод create.
Но модель User отличается. Модель пользователя не имеет create, вместо этого есть create_user. и CreateView не знает об этом. Я предлагаю вам использовать класс View следующим образом:
class UserRegisterView(View):
form_class = UserRegistrationForm
template_name = 'account/register.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('home:home')
return super().dispatch(request, *args, **kwargs)
def get(self, request):
form = self.form_class()
return render(request, self.template_name, {'form':form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
cd = form.cleaned_data
User.objects.create_user(cd['username'], cd['email'], cd['password1'])
messages.success(request, 'you registered successfully', 'success')
return redirect('home:home')
return render(request, self.template_name, {'form':form})
этот сниппет полностью работает.
Вы должны сделать POST-запрос к представлению newuser, так:
<form action="{% url 'app:newuser' %}" method="post">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Register">
</form>
Однако вы не можете использовать простой ModelForm: пароли в Django хэшируются, и ModelForm будет не делать этого, или, по крайней мере, не автоматически.
Вы можете использовать UserCreationForm [Django-doc] для правильного хэширования, это поле также использует два поля пароля, которые будут проверены.
Если вы хотите реализовать пользовательский ModelForm, то вам необходимо реализовать функциональность хеширования пароля в форме модели:
class NewUserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username','email','password']
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
и затем подключите это к CreateView с:
class NewUserView(generic.CreateView):
model = User
form_class = NewUserForm
template_name = 'app/user_form.html'
success_url = reverse_lazy('cadastro')
Примечание: В Django представления, основанные на классах (CBV), часто имеют суффикс
…View, чтобы избежать столкновения с именами моделей. Поэтому вы можете переименовать класс представления вNewUserView, вместо.NewUser