My password_reset_email.html in django-registration looks like this:
{% blocktrans %}
To reset your password, please click the following link:
{% endblocktrans %}
<body>
<p>
<a href="http://{{ site.domain }}{% url 'auth_password_reset_confirm' uid token %}">
Reset password
</a>
</p>
</body>
{% blocktrans %}
Django is picking up the url but not {{site.domain}}. Yet, when I have the same code in the registration process {{site.domain}} was valid. What makes the password_reset_email.html different than the registration process?
Thanks.
django-registration (or rather django.contrib.auth) doesn't use context processors for rendering emails. You will have to add {{ site }} to the context manually during rendering. Basically you'll have to customize django-registration's urls. Something along those line:
from django.contrib.sites.models import Site
from django.contrib.auth import views as auth_views
....
url(r'^password/reset/$', auth_views.password_reset,
{'post_reset_redirect': reverse_lazy('auth_password_reset_done'),
'extra_email_context': {'site': Site.objects.get_current()}},
name='auth_password_reset'),
....
Related
I have created views in Django that use LoginRequiredMixin. However, whenever I log in and am to be redirected to another url, the url I am redirected to ends with multiple slashes instead of the usual 1 slash at the end of a django url.
One of my views:
class BookListView(LoginRequiredMixin, ListView):
model = Book
# paginate enables the list view to fetch a certain number of records per page. This is
# useful when the records are plenty and it is not possible to display all in one page.
paginate_by = 3
My login.html template:
{%extends 'catalog/base_generic.html'%}
{%block content%}
{%if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{%if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.
</p>
{% else %}
<p>Please login to view this page.</p>
{% endif %}
{% endif %}
<form method="POST", action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{form.username.label_tag}}</td>
<td>{{form.username}}</td>
</tr>
<tr>
<td>{{form.password.label_tag}}</td>
<td>{{form.password}}</td>
</tr>
</table>
<input type="submit" value="Login"/>
<input type="hidden" name="next" value={{next}}/>
</form>
<P>
Forgot Password?
</P>
{% endblock %}
When I am just logging in, all seems Okay:
Login Page
However, after login, this happens:
Error Message with multiple slashes at the end
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/catalog/books///
Using the URLconf defined in locallibrary.urls, Django tried these URL patterns, in this order:
admin/
catalog/ [name='index']
catalog/ books/ [name='books']
catalog/ book/<int:pk>/ [name='book-detail']
catalog/ authors/ [name='authors']
catalog/ author/<int:pk>/ [name='author-detail']
accounts/
^static/(?P<path>.*)$
The current path, catalog/books///, didn’t match any of these.
You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
I can't figure out what I am doing wrong. Please help!
you forgot some quotes around {{ next }}
change it to
<input type="hidden" name="next" value="{{next}}"/>
#settings.py
APPEND_SLASH: bool = True # by default
Setting it to False will resolve your extra slash issue. Check the documentation; there are some drawbacks if set to False in production.
Make Use of Doctests Module to debug what's causing the issue.
>>> from django.test import SimpleTestCase
>>> from django.test import Client
>>>
>>>
>>> class TestRedirect(SimpleTestCase):
... """There is a good chance it will return redirect and
... and return 301 response; if APPEND_SLASH is causing the issue."""
>>>
>>>
>>> def test_catalog_book(self):
... client = Client()
... response = client.get("/catalog/book/")
... self.assertEqual(response.status_code, 301)
Read the documentation of advanced testings
>>> response = c.get('/redirect_me/', follow=True)
>>> response.redirect_chain
[('http://testserver/next/', 302), ('http://testserver/final/', 302)]
I don't have the views.py using PasswordResetViews!
i am using the django password reset but i want my template to behave differently when it come from password_rest_email and from password_reset_confirm
urls.py
from django.conf.urls import url,include
#from django.urls import path
from dappx import views
from django.contrib.auth.views import PasswordResetView,PasswordResetDoneView,PasswordResetCompleteView,PasswordResetConfirmView
# SET THE NAMESPACE!
app_name = 'dappx'
# Be careful setting the name to just /login use userlogin instead!
urlpatterns=[
url('register/', views.register, name='register'),
url('user_login/', views.user_login, name='user_login'),
url('google_login/', views.google_login, name='google_login'),
url('special/', views.special, name='special'),
url('logout/', views.user_logout, name='logout'),
url(r'^', include('django.contrib.auth.urls')),
url('password_reset/', PasswordResetView.as_view(), name='password_reset'),
url('password_reset/done/', PasswordResetDoneView.as_view(), name='password_reset_done'),
url('reset/<uidb64>/<token>/', PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
]
i need that template i.e(password_reset_confirm) to show email is send when it come from password_reset_email and show password reset successful if it come from password_reset_confirm
password_reset_complete.html
{% extends 'dappx/base.html' %}
{% block title %}Check your Email{% endblock %}
{% block body_block %}
<div class="row no-gutters">
<div class="col-12 col-sm-6 col-md-8"></div>
<div class="col-6 col-md-4">
<div class="jumbotron">
<h4>The password reset link has been sent to youre Email</h4>
<br>
<p>Check your email to reset the password. You can log in now on the log in page.</p>
<br>
</div>
</div>
{% endblock %}
Seems duplicate of Django: getting previous url
You can always pass GET variable with information you want and in subsequent view, it can be used directly.
I can not comment posts yet, so I just write this as an answer. The following link provides a tutorial about the django built in authentication. There is logic for a view that tells the user that an email has been sent 'Password Reset Done View' and logic for a view that tells if it was successfull 'Password Reset Complete View'.
Django Tutorial
I am making the backend for a mobile app and using Django with Userena for the user management. I made the sign in and sign up using Django REST framework and everything works fine. The only thing I need to do now is to implement the "forget password" functionality. I wanted to use the already implemented one from Userena, but I cannot get rid of the error "CSRF token missing or incorrect" even after using the csrf_exempt dectorator. What am I doing worng?
urls.py
from django.contrib.auth.views import password_reset
from django.views.decorators.csrf import csrf_exempt
...
urlpatterns = patterns(
'',
url(r'^password/mobile/reset/$',
csrf_exempt(password_reset),
{'template_name': 'userena/password_reset_form.html',
'email_template_name': 'userena/emails/password_reset_message.txt',
'extra_context': {'without_usernames': userena_settings.USERENA_WITHOUT_USERNAMES}
},
name='userena_password_mobile_reset'),
)
passowrd_reset_form.html
{% extends 'userena/base_userena.html' %}
{% load i18n %}
{% block title %}{% trans "Reset password" %}{% endblock %}
{% block content %}
<form action="" method="post">
<fieldset>
<legend>{% trans "Reset Password" %}</legend>
{% csrf_token %}
{{ form.as_p }}
</fieldset>
<input type="submit" value="{% trans "Send password" %}" />
</form>
{% endblock %}
If you do a GET request before POSTing to the password reset view, you get the CSRF token in a cookie, which you can then send in your POST request.
If you insist on exempting the view: I think the problem lies in the way the CSRF protection is applied to the password_reset view. It is explicitly decorated by csrf_protect.
To have a closer look at the problem, lets assume original_password_reset_view is password_reset without the csrf_protect. Basically, you are doing this:
csrf_exempt(csrf_protect(original_password_reset_view))
# ^^ your code
# ^^ the decorator in django.contrib.auth.views
And adding in the effect of the CsrfViewMiddleware, we get the equivalent of
csrf_protect(csrf_exempt(csrf_protect(original_password_reset_view)))
csrf_protect is just a middleware-turned-decorator from CsrfViewMiddleware. csrf_exempt on the other hand simply sets csrf_exempt=True on its argument. So the middleware, represented by the outer csrf_protect, sees the csrf_exempt=True value on the view and disables its CSRF projection. It negates the outer csrf_protect. So we have:
csrf_protect(original_password_reset_view)
The view is still protected. Basically, there is no sane way around. (An insane way: write a middleware that sets request.csrf_processing_done = True for that specific URL. Don't do that...)
Can someone please explain in details how to make a registration and authentication in as easy words as possible ? I made authentication (login) with django.contrib.auth but what I want to get is a full register(social/non)+login. Already saw the django-allauth, django-social-auth, django-social but still can't get it working without hacking a lot. Heard that django-registration and django-profiles can make it a lot easier, but i can't handle it. For example,
~/.virtualenvs/plinter/lib/python2.7/site-packages/registration/backends/default/urls.py
needs a small hack to work:
# from django.views.generic.simple import direct_to_template
from django.views.generic import RedirectView
...
RedirectView.as_view(url='/registration/activation_complete.html'),
# direct_to_template,
# {'template': 'registration/activation_complete.html'},
...
The DjangoBook gives simple examples of Contact and search forms. But i can't expand it on user registration and login.
So can anyone give kis example of working registration and login?
Update
Here is a simple example of login. Now django-allauth or social auth or registration2 are in consideration...
Update2
django-allauth seems to be the best solution for easier authentication. Add correctly apps in settings, register fb/google/etc apps and register through admin and use template inheritance to change default pages design.
THIS is a very good tutorial about login & Co. It explains very well how to perform login by ourself ad override existing django login pages.
UPDATE:
Here Overview for Registration and Login. For more details go to the link.
To Register:
Views and URLs
Go to the lower site folder (where the settings.py file is) and open
the views.py file. At the top make sure the following imports are
included. Add them if not:
from django.shortcuts import
render_to_response from django.http import HttpResponseRedirect from
django.contrib.auth.forms import UserCreationForm from
django.core.context_processors import csrf
Below that add the following functions (you can put them after the
Login functions):
def
register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register/complete')
else:
form = UserCreationForm()
token = {}
token.update(csrf(request))
token['form'] = form
return render_to_response('registration/registration_form.html', token)
def registration_complete(request):
return render_to_response('registration/registration_complete.html')
Open the urls.py file in the site folder (same folder as
settings.py). Below urlpatterns = patterns('', insert the following
lines.
# Registration URLs
url(r'^accounts/register/$', 'simplesite.views.register', name='register'),
url(r'^accounts/register/complete/$', 'simplesite.views.registration_complete',
name='registration_complete'),
Templates We will assume your site already has a templates
directory and a base.html file with the navigation bar. Open the
base.html file and in the nav element add a navigation menu link to
the login page
register
If one does not already exist, go to the templates folder and create
a folder inside it named registration. Create a file called
registration_form.html, save it to the templates/registration folder,
then populate it with the following:
{% extends "base.html" %} {% block title %}Register{%
endblock %} {% block content %}
<h2>Registration</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form.as_p}} <input type="submit" value="Register" />
</form>
{% endblock %}
Create a file called registration_complete.html, save it to the
templates/registration folder, and populate it with the following:
{% extends "base.html" %} {% block title %}You are
Registered{% endblock %} {% block content %}
<h2>Thank you for Registering</h2> <p>Please Login</p>
{% endblock %}
To Login:
Views and URLs Open the views.py file in the lower site folder (where the settings.py file is). If there isn't one then create and
save it. At the top of the file insert the following import: from
django.shortcuts import render_to_response Below that you only need to
add one function rendering the loggedin page. The other functions
(login and logout) are in the views.py file in the Django Auth folder.
def loggedin(request):
return render_to_response('registration/loggedin.html')
# Optionally, if you want to show their username when they login then call their username in the view. Change the loggedin function to:
def loggedin(request):
return render_to_response('registration/loggedin.html',
{'username': request.user.username})
Open the urls.py file in the site folder (same folder as settings.py).
Below urlpatterns = patterns('', insert the following lines.
# Auth-related URLs:
url(r'^accounts/login/$', 'django.contrib.auth.views.login', name='login'),
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', name='logout'),
url(r'^accounts/loggedin/$', 'simplesite.views.loggedin', name='loggedin'),
With simplesite being the name of the folder that holds the views.py
file that you are calling. Open the settings.py file and at the bottom
insert LOGIN_REDIRECT_URL = '/accounts/loggedin/'. Django's default
is to redirect to /accounts/profile when you log in, which is fine if
you have an profile page at that url. If not you need to change your
settings default for the Login redirect url to the one holding your
loggedin.html page.
Templates
We will assume your site already has a templates directory and a
base.html file with the navigation bar. Open the base.html file and in
the nav element add a navigation menu link to the login page login Add a logout link too logout Create a directory called
registration inside the templates folder. If you do this through the
command line, type mkdir registration Create a file called login.html,
save it to the templates/registration folder, and populate it with the
following:
{% extends "base.html" %}
{% block title %}Log In{% endblock %}
{% block content %}
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="login" />
</form>
{% endblock %}
{{ form.as_table }} uses the Django Forms module to create the form.
You can create an unformatted form by using {{ form }} without the
HTML table tags, or have each field put inside paragraph tags with {{
form.as_p }}, or as an unordered list {{ form.as_ul }}. Optionally, you
can also lay out your own form structure and use the form field tags
as follows:
{% extends "base.html" %}
{% block title %}Log In{% endblock %}
{% block content %}
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
{% if form.errors %}
<p>Your Username or Password were not entered correctly. Please try again.</p>
{% endif %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
<td>{{ form.username.errors }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
<td>{{ form.password.errors }}</td>
</tr>
</table>
<input type="submit" value="login" />
</form>
{% endblock %}
Create a file called loggedin.html, save it to the
templates/registration folder, and populate it with the following:
{% extends "base.html" %}
{% block title %}Logged In{% endblock %}
{% block content %}
<h2>You are logged in</h2>
{% endblock %}
If you want to display the username, you would make the adjustment to
the view discussed in the views section. Then change the loggedin.html
template to the below (change the wording as you see fit):
{% extends "base.html" %}
{% block title %}Logged In{% endblock %}
{% block content %}
<h1>Welcome {{username}}</h1>
<p>Thank you for logging in.</p>
<p>Logout</p>
{% endblock %}
Create a file called logged_out.html, save it to the
templates/registration folder and populate it with the following:
{% extends "base.html" %}
{% block title %}Logged Out{% endblock %}
{% block content %}
<h2>Logged out!</h2>
<p>Log back in</p>
{% endblock %}
Trix's approach worked for me, but the logout link was redirecting to the admin logout, instead of logged_out.html.
To fix the redirect, I added a next option to the href:
Logout
In templates/registration:
Renamed logged_out.html to loggedout.html; the underscore caused it to still route to the admin logout page.
In views.py:
def loggedout(request):
return render_to_response('registration/loggedout.html')
And finally, in urls.py:
url(r'^myapp/loggedout/$', 'myapp.views.loggedout', name='loggedout'),
I wanted to redirect the users in my app to their users page if they were already logged in and tried to go directly to "../login/". I've found this answer:
Django: Redirect logged in users from login page
It works fantastic until I decide to hit the "Registration" link I have below my login fields. I don't know why but when I hit it, I get redirect to the login page again but the only thing that changes is the url, for some reason it becomes "http://localhost:8000/users/login/?next=/users/register/", and it wont take me to my registration page.
Why the "next" variable changes if I've set it with another url in the login template like so:
{% extends "base.html" %}
{% block title %}User Login{% endblock %}
{% block head %}User Login{% endblock %}
{% block content %}
{% if form.errors %}
<p>User name or password is incorrect.</p>
{% endif %}
<form method="post" action="{% url login %}">
{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="submit" value="Login" />
<input type="hidden" name="next" value="users/"/>
</form>
<li>Register</li>
{% endblock %}
I'm using django1.4 and python 2.7. My urls.py are:
For the whole application:
urlpatterns = patterns('',
url(r'^$', main_page, name="main_page"),
url(r'^users/',include('user_manager.urls')),
)
For the user_manager module:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^(\w+)/$', user_page),
url(r'^register/$', register_page),
)
Do you have a #login_required decorator on that register_page view? If so, remove it
Ok I've found the problem. Django checks the urls regex in order so the "register" url was matching the "(\w+)/" intended to work for the users pages. So all I had to do is put that url at the end, the urls.py now looks like this:
urlpatterns = patterns('user_manager.views',
url(r'^$', users, name="user_page"),
url(r'^logout/$', user_logout, name="logout"),
url(r'^login/$', user_login, name="login"),
url(r'^register/$', register_page),
url(r'^(\w+)/$', user_page),
)
Nevertheless I still don't understand quite well why that mistaken match was changing the next value. I know that caused it but I don't know why...
Thank you very much for your time!