我创建了基于类的视图rest api。我使用django djoser。我的激活模板和所有链接的工作。但现在我正在重置密码,我使用模板休息密码。但是给出405错误。我正在重置密码链接。另外,我的html页面是工作的,但当我改变我的密码,点击提交它给我405错误
views.py
class ResetPasswordView(View):
def get (self, request, uid, token):
return render(request, 'password_reset_email.html') # display activation page when user click on link which recieved fron gmail
def post (self, request,uid,token):
print('In Password Reset Post')
new_password=request.post.get("new_password")
print("new_password :",new_password)
re_new_password=request.post.get("re_new_password")
print("re_new_password : ",re_new_password)
payload = json.dump({'uid': uid, 'token': token, 'new_password': new_password, 're_new_password': re_new_password})
protocol = 'https://' if request.is_secure() else 'http://' # will evaluate to True if the connection is secure (HTTPS: HTTP over TLS) or False if non-secure (standard HTTP).
web_url = protocol + request.get_host() + '/'
password_reset_url = "users/reset_password_confirm/" # url used for activate user
password_post_url = web_url + AUTHENTICATION_BASE_ROUTE + password_reset_url # for activate user
print('url : ', password_post_url)
response = request.post(password_post_url,data=payload)
return HttpResponse(response.text)
urls . py
re_path(r'^password/reset/confirm/(?P<uid>[w-]+)/(?P<token>[w-]+)/$', ResetPasswordView.as_view()),
password_reset_email.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p}}
<div class="container">
<h1>Register</h1>
<p>Please fill this form to create an account.</p>
<hr>
<label for="psw"><b>New Password</b></label>
<input type="password" placeholder="Enter Password" name="new_password" id="new_password" required>
<label for="psw-repeat"><b>Repeat Password</b></label>
<input type="password" placeholder="Repeat Password" name="re_new_password" id="re_new_password"
required>
<hr>
<button type="submit" class="registerbtn">Register</button>
</div>
</form>
settings.py
DJOSER = {
# 'activation': 'user_profile.email.ActivationEmail',
'LOGIN_FIELD': 'email',
'USER_CREATE_PASSWORD_RETYPE': True,
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'SEND_CONFIRMATION_EMAIL': True,
'SET_USERNAME_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'USERNAME_RESET_CONFIRM_URL': 'email/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': 'activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'EMAIL':
{
'activation': 'user_profile.email.ActivationEmail',
'conformation_email':'user_profile.email.ConfirmationEmail',
'password_reset_email':'user_profile.email.PasswordResetEmail',
'PasswordChangedConfirmationEmail':'user_profile.email.PasswordChangedConfirmationEmail'
},
'SERIALIZERS': {
'user_create': 'user_profile.serializer.UserSerializer',
'user': 'user_profile.serializer.UserSerializer',
}
}
AUTHENTICATION_BASE_ROUTE = 'authentication/v2/'
我正在重置密码链接。另外,我的html页面是工作的,但当我改变我的密码,点击提交它给我405错误
-
您需要更改json。转储到json.dumps
-
requests.post试试。您可以将请求导入到终端以查看反馈,而无需总是刷新页面
-
考虑添加更多错误处理(密码验证、hostrongite、提交响应码)
短答:
import json
import requests
payload = json.dumps({
'uid': kwargs.get('uid'),
'token': kwargs.get('token'),
'new_password': password,
're_new_password': password_confirmation,
})
response = requests.post(url, data=payload, headers = headers)
长答:
我发现使用这种类型的视图对我来说效果最好。
@api_view(('GET', 'POST'))
@renderer_classes((TemplateHTMLRenderer, JSONRenderer))
@permission_classes([AllowAny])
def reset_user_password(request, **kwargs):
# Uses djoser to reset password
if request.POST:
password = request.POST.get('password')
password_confirmation = request.POST.get('password_confirmation')
我还在提交时添加了一些密码验证。我相信这些代码可以通过简单地使用Django表单(它将在页面内而不是在提交时进行验证)来避免,但我觉得没有必要这样做。
# Will eventually switch to a form that can process this information live
if password.isdigit() or len(password)<8:
message = "Your password must contain at least 8 characters and cannot be entirely numeric."
return render(request, 'core/password/reset_password.html', {'message': message})
elif password.isdigit():
message = "Your password cannot be entirely numeric."
return render(request, 'core/password/reset_password.html', {'message': message})
elif len(password)<8 or len(password_confirmation)<8:
message = "Your password is too short, it must contain at least 8 characters."
return render(request, 'core/password/reset_password.html', {'message': message})
elif password != password_confirmation:
message = "The passwords you have entered do not match. Please re-enter and try again."
return render(request, 'core/password/reset_password.html', {'message': message})
现在格式化数据…
else:
# Data to accept -> the uid and token is obtained as keyword arguments in the url
payload = json.dumps({
'uid': kwargs.get('uid'),
'token': kwargs.get('token'),
'new_password': password,
're_new_password': password_confirmation,
})
# PROTOCOL
protocol = 'https'
if bool(request) and not request.is_secure():
protocol = 'http'
给码头工人的重要提示->如果你使用Docker来托管你的站点
我可以使用邮差或简单的终端发送到我的Docker,但它在我的代码中不起作用。经过几个小时的痛苦,事实证明我发布错误的端口。外部端口为5000,外部端口为5090。
# - - -- URLS -- - -
# Current Site -> needs to be adjusted depending on the docker
hosted_site = request.get_host()
docker_site = '0.0.0.0:5000'
# Endpoint
djoser_password_reset_url = 'auth/users/reset_password_confirm/'
# COMPLETE URL
if hosted_site == '0.0.0.0:5090':
url = '{0}://{1}/{2}'.format(protocol, docker_site, djoser_password_reset_url)
else:
url = '{0}://{1}/{2}'.format(protocol, hosted_site, djoser_password_reset_url)
# HEADERS
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=payload, headers = headers)
# Verifying the request sent - server returns 204 (no content)
if response.status_code == 204:
messages.success(request, 'Your password has been reset successfully!')
我还创建了一个成功页面,以便在请求成功发送后将它们重新路由到。使用反向允许站点正确重定向。否则,它将把重定向url附加到当前站点的url。
# Redirect to success, your password has been reset
return HttpResponseRedirect(reverse('reset-password-confirm'))
# Error handling if the response code is not 204
else:
response_object = response.json()
response_object_keys = response_object.keys()
for key in response_object_keys:
decoded_string = response_object.get(key)[0].replace("'", "'")
messages.error(request, f'{decoded_string}')
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
# If the request is GET
return render(request, '[your app here]/password/reset_password.html')