How to use different form in Django-Registration - django

Django-Registration has several form classes in the forms.py file. One is "class RegistrationFormTermsOfService(RegistrationForm) ..
What do I change in the rest of Django Registration code to enable this form in my registration flow instead of RegistrationForm?

Updating the accepted answer to conform with Django 1.5 and the latest version of django-registration:
in urls.py:
from registration.forms import RegistrationFormTermsOfService
from registration.backends.default.views import RegistrationView
urlpatterns = patterns('',
url(r'^accounts/register/$', RegistrationView.as_view(form_class=RegistrationFormTermsOfService), name='registration_register'),
# your other URLconf stuff follows ...
)
then update the registration_form.html template and add a tos field, e.g.:
<p>
<label for="id_tos">I accept the terms of service</label>
{% if form.tos.errors %}
<p class="errors">{{ form.tos.errors.as_text }}</p>
{% endif %}
{{ form.tos }}
</p>

You can simply go into your urls.py and override the form class by doing something like:
from registration.forms import RegistrationFormTermsOfService
(r'^accounts/register/$', 'registration.views.register', {'form_class' : RegistrationFormTermsOfService}),

Here is a practical example using a custom form and backend which sets username == email address, and only prompts the user for an email address at registration. In, for e.g. my_registration.py:
from django.conf import settings
from django.contrib.sites.models import RequestSite
from django.contrib.sites.models import Site
from registration import signals
from registration.forms import RegistrationForm
from registration.models import RegistrationProfile
from registration.backends.default import DefaultBackend
class EmailRegistrationForm(RegistrationForm):
def __init__(self, *args, **kwargs):
super(EmailRegistrationForm,self).__init__(*args, **kwargs)
del self.fields['username']
def clean(self):
cleaned_data = super(EmailRegistrationForm,self).clean()
if 'email' in self.cleaned_data:
cleaned_data['username'] = self.cleaned_data['username'] = self.cleaned_data['email']
return cleaned_data
class EmailBackend(DefaultBackend):
def get_form_class(self, request):
return EmailRegistrationForm
In my_registration_urls.py:
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from registration.views import activate
from registration.views import register
urlpatterns = patterns('',
url(r'^activate/complete/$',
direct_to_template,
{ 'template': 'registration/activation_complete.html' },
name='registration_activation_complete'),
# Activation keys get matched by \w+ instead of the more specific
# [a-fA-F0-9]{40} because a bad activation key should still get to the view;
# that way it can return a sensible "invalid key" message instead of a
# confusing 404.
url(r'^activate/(?P<activation_key>\w+)/$',
activate,
{ 'backend': 'my_registration.EmailBackend' },
name='registration_activate'),
url(r'^register/$',
register,
{ 'backend': 'my_registration.EmailBackend' },
name='registration_register'),
url(r'^register/complete/$',
direct_to_template,
{ 'template': 'registration/registration_complete.html' },
name='registration_complete'),
url(r'^register/closed/$',
direct_to_template,
{ 'template': 'registration/registration_closed.html' },
name='registration_disallowed'),
(r'', include('registration.auth_urls')),
)
Then in your core urls.py, ensure you include:
url(r'^accounts/', include('my_registration_urls')),

You'll need to write a new registration form somewhere in your project. You can inherit off of the existing authentication form if you're just expanding new fields. You'll then want to write a new backend to process the form. Finally you'll need to write your own url and auth_urls and redefine the urls to switch the backend and authentication form in the views by changing the variables that get passed to the view.
It's helpful to break open the source to see how things are working. I base my structure off of the original django-registration code to keep things consistent.

As to django 1.11 and django-registration 2.2 there are some updated imports... so if you get "No module named 'registration'" this could be the problem...
Replace:
from registration.backends.hmac.views import RegistrationView
by from django_registration.backends.activation.views import RegistrationView
from registration.forms import RegistrationForm
by from django_registration.forms import RegistrationForm
include('django_registration.backends.hmac.urls') in urls
by include('django_registration.backends.activation.urls')
Just to name a few... ;)
Src: https://django-registration.readthedocs.io/en/3.0/custom-user.html

Related

Is there a way to show Django messages in Django admin site?

I need to display a Django message on the Django admin index site. I am looking for a way to add certain conditions for the message to be displayed and pass it to Django index site. Is there a way to achieve that?
You should do this by customizing your django admin stie. In the admin.py module of your app you should define a new AdminSite and override the index method. In the index method you can add your custom messages:
# [<app>/admin.py]
from django.views.decorators.cache import never_cache
from django.contrib import admin
class CustomAdminSite(admin.AdminSite):
#never_cache
def index(self, request, extra_context=None):
messages.add_message(request, messages.INFO, 'This is a message.')
return super().index(request, extra_context)
Then don't forget to change the default admins site to your CustomAdminSite:
# [<app>/admin.py]
admin_site = CustomAdminSite(name='myadmin')
Then in the project's urls.py use your custom admin_site:
# [<project>/urls.py]
from <app>.admin import admin_site
urlpatterns = [
...
path('', admin_site.urls),
]

Django redirecting to a different view in another app

There are many similar questions to mine on Stack Overflow, but none which solve my problem.
I have a class-based view which accepts files, and once a valid file is found, I would like the website to redirect the user to a template inside a different app, passing in some parameters.
I've seen others put an extra path in 'urlpatterns' and get the view from there. But doing this only makes a GET signal on my command prompt, but not actually changing the web url.
views.py
from django.shortcuts import render, redirect # used to render templates
from django.http import JsonResponse
from django.views import View
from .forms import UploadForm
from .models import FileUpload
class UploadView(View):
def get(self, request):
files_list = FileUpload.objects.all()
return render(self.request, 'upload/upload.html', {'csv_files': files_list})
def post(self, request):
form = UploadForm(self.request.POST, self.request.FILES)
if form.is_valid():
csv_file = form.save()
data = {'is_valid': True,
'name': csv_file.file.name,
'url': csv_file.file.url,
'date': csv_file.uploaded_at}
# REDIRECT USER TO VIEW PASSING 'data' IN CONTEXT
return redirect('graph:chart', file_url=csv_file.file.url)
else:
data = {'is_valid': False}
return JsonResponse(data)
urls.py
from django.urls import path
from . import views
app_name = "upload"
urlpatterns = [
path('', views.UploadView.as_view(), name='drag_and_drop'),
]
urls.py (of other app)
from django.urls import path
from . import views
app_name = "graph"
urlpatterns = [
path('', views.page, name='chart'),
]
You can specify an app name and use exactly the redirect shortcut as you started:
https://docs.djangoproject.com/en/2.1/topics/http/urls/#naming-url-patterns
in the other app urls.py define app_name = 'other_app', and then use redirect('other_app:url_name', parameter1=p1, parameter2 = p2)
you can name easily your parameters either using path (Django >=2.0) or url (re_path for Django >=2.0), for instance:
from django.urls import path
from . import views
urlpatterns = [
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]

Django does not match urls

I've been working on a django web app (using Django 1.3), a web catalogue of products, and it was working fine until I was asked to add a custom admin site. I'm fully aware of the Django admin site, but the client is very old-fashioned, and is tech-ignorant so I have to make a "for dummies" version admin site. The root urlconf:
from django.conf.urls.defaults import *
from django.views.generic import TemplateView
from store.models import Category
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^^$', TemplateView.as_view(
template_name='homepage.html',
get_context_data=lambda: {
'crumb': 'home',
'category_list':Category.objects.all()
}
),
name='home'),
url(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/img/favicon.ico'}),
url(r'^store/', include('store.urls', app_name='store', namespace='store')),
)
And the urlconf for the store app:
from django.conf import settings
from django.conf.urls.defaults import *
from store import views
urlpatterns = patterns ('',
url(r'^category/$', views.get_brands, name='get_brands'),
url(r'^(\w+)/$', views.GalleryView.as_view(), name='gallery'),
url(r'^(\w+)/(\w+)/$', views.GalleryView.as_view(), name='gallery'),
)
and the original views:
from django.http import Http404
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView
from store.models import Category, Brand, Product
def get_brands(request):
q = request.GET.get('q')
if q is not None:
category = get_object_or_404(Category, slug__iexact=q)
try:
brands = category.brands.all()
except:
brands = []
template = 'infobox.html'
data = {
'category': category,
'brands': brands,
}
return render( request, template, data )
class GalleryView(ListView):
context_object_name = 'product_list'
template_name = 'store/gallery.html'
def get_queryset(self):
self.category = get_object_or_404(Category, slug__iexact=self.args[0])
try:
brand = Brand.objects.get(slug__iexact = self.args[1])
self.brand_name = brand.name
except:
#no brand is specified, show products with no brand
if self.category.category_products.filter(brand__isnull=True):
#if there are products with no brand, return those
return self.category.category_products.filter(brand__isnull=True)
else:
#if all products have a brand, return the products of the first brand
all = self.category.brands.all()
if all:
brand = all[0]
self.brand_name = brand.name
return brand.brand_products.all()
else:
raise Http404
else:
#brand is specified, show its products
return Product.objects.filter(category=self.category, brand=brand)
def get_context_data(self, **kwargs):
context = super(GalleryView, self).get_context_data(**kwargs)
category = self.category
category_brands = self.category.brands.all()
context['category_list'] = Category.objects.all()
context['category'] = category
context['crumb'] = category.name
context['category_brands'] = category_brands
try:
context['brand'] = self.brand_name
except:
context['brand'] = None
return context
Now, my custom admin app was working fine on my local dev environment, but when I added the new urls and views to prod, Django doesn't seem to match any of the new urls. The original views and urls still work, but none of the new urls get matched and I just keep getting a 404 Not Found error.
The updated urlconf:
from django.conf import settings
from django.conf.urls.defaults import patterns, include, url
from django.contrib.auth.decorators import login_required
from store import views
admin_urls = patterns ('',
url(r'^$', login_required(views.AdminIndexView.as_view()), name='admin_index'),
url(r'^add/(\w+)/$', login_required(views.AdminAddView.as_view()), name='admin_add'),
)
urlpatterns = patterns ('',
url(r'^category/$', views.get_brands, name='get_brands'),
url(r'^(\w+)/$', views.GalleryView.as_view(), name='gallery'),
url(r'^(\w+)/(\w+)/$', views.GalleryView.as_view(), name='gallery'),
url(r'^login/$', views.admin_login, name='login'),
url(r'^logout/$', views.admin_logout, name='logout'),
url(r'^logout/success/$', views.admin_logout_success, name='logout_success'),
url(r'^test/', views.test, name='test'),
url(r'^admin/', include(admin_urls, namespace='admin')),
url(r'^ajax/$', views.ajax_request, name='ajax_request'),
)
Note that not even the simple '/store/test/' url does not get matched. I'm not really sure why Django isn't matching my urls, and any help is appreciated.
I'm not exactly sure what was happening since all of my templates linked to other pages using the {% url %} tag, but I think the reason my urls were getting muddled up was because I was using the r'^(\w+)/$' regex, so it was matching any word. I simply moved the urlconfs with the (\w+) rule to the bottom of urls.py, and refactored them to be a little more specific and they were gold again.
The updated urlconf:
from django.conf import settings
from django.conf.urls.defaults import patterns, include, url
from django.contrib.auth.decorators import login_required
from store import views
admin_urls = patterns ('',
)
urlpatterns = patterns ('',
url(r'^category/$', views.get_brands, name='get_brands'),
url(r'^(\w+)/$', views.GalleryView.as_view(), name='gallery'),
url(r'^(\w+)/(\w+)/$', views.GalleryView.as_view(), name='gallery'),
url(r'^login/$', views.admin_login, name='login'),
url(r'^logout/$', views.admin_logout, name='logout'),
url(r'^logout/success/$', views.admin_logout_success, name='logout_success'),
url(r'^ajax/$', views.ajax_request, name='ajax_request'),
url(r'^administration/$', login_required(views.AdminIndexView.as_view()), name='admin_index'),
url(r'^administration/add/(\w+)/$', login_required(views.AdminAddView.as_view()), name='admin_add'),
)
As you mentioned in the comments, removing login_required fixes the problem. Here's what the django docs have to say about the decorator:
login_required() does the following:
If the user isn’t logged in, redirect to settings.LOGIN_URL, passing the current absolute path in the query string. Example:
/accounts/login/?next=/polls/3/.
If the user is logged in, execute the view normally
[...] Note that if you don't specify the login_url parameter, you'll
need to map the appropriate Django view to settings.LOGIN_URL.
In other words, it goes to a default url you can override in settings.LOGIN_URL.
Now here's what I think happened - I think you defined your own login here:
url(r'^login/$', views.admin_login, name='login'),
And because the login_required in the new urls pointed at the default url, which doesn't exist it returned 404. However, when you configured the login_required views after your other urls:
url(r'^login/$', views.admin_login, name='login'),
...
url(r'^administration/$', login_required(views.AdminIndexView.as_view()), name='admin_index'),
url(r'^administration/add/(\w+)/$', login_required(views.AdminAddView.as_view()), name='admin_add'),
it worked. Why is that? You didn't overrid LOGIN_URL here right? But you sort of did - because at this point, you redefined the namespace 'login' to point to your own view. Now this isn't mentioned anywhere in the docs, but it makes sense, and looking at the default admin templates you can see this is the namespace being used.
Does that make sense to you?

How to redirect users to a specific url after registration in django registration?

So I am using django-registration app to implement a user registration page for my site. I used Django's backends.simple views which allows the users to immediately login after registration. My question is how do I redirect them to my other app's page located in the same directory as the project.
Here is what my main urls.py looks like:
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
url(r'^accounts/', include('registration.backends.simple.urls')),
url(r'^upload/', include('mysite.fileupload.urls')),
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
# url(r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# url(r'^admin/', include(admin.site.urls)),
)
import os
urlpatterns += patterns('',
(r'^media/(.*)$', 'django.views.static.serve', {'document_root': os.path.join(os.path.abspath(os.path.dirname(__file__)), 'media')}),
)
fileupload is the name of the other app I have in the project directory mysite.
This is what the backends.simple.urls looks like:
"""
URLconf for registration and activation, using django-registration's
one-step backend.
If the default behavior of these views is acceptable to you, simply
use a line like this in your root URLconf to set up the default URLs
for registration::
(r'^accounts/', include('registration.backends.simple.urls')),
This will also automatically set up the views in
``django.contrib.auth`` at sensible default locations.
If you'd like to customize registration behavior, feel free to set up
your own URL patterns for these views instead.
"""
from django.conf.urls import include
from django.conf.urls import patterns
from django.conf.urls import url
from django.views.generic.base import TemplateView
from registration.backends.simple.views import RegistrationView
urlpatterns = patterns('',
url(r'^register/$',
RegistrationView.as_view(),
name='registration_register'),
url(r'^register/closed/$',
TemplateView.as_view(template_name='registration/registration_closed.html'),
name='registration_disallowed'),
(r'', include('registration.auth_urls')),
)
And here is the backends.simple.views:
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth import login
from django.contrib.auth.models import User
from registration import signals
from registration.views import RegistrationView as BaseRegistrationView
class RegistrationView(BaseRegistrationView):
"""
A registration backend which implements the simplest possible
workflow: a user supplies a username, email address and password
(the bare minimum for a useful account), and is immediately signed
up and logged in).
"""
def register(self, request, **cleaned_data):
username, email, password = cleaned_data['username'], cleaned_data['email'], cleaned_data['password1']
User.objects.create_user(username, email, password)
new_user = authenticate(username=username, password=password)
login(request, new_user)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request)
return new_user
def registration_allowed(self, request):
"""
Indicate whether account registration is currently permitted,
based on the value of the setting ``REGISTRATION_OPEN``. This
is determined as follows:
* If ``REGISTRATION_OPEN`` is not specified in settings, or is
set to ``True``, registration is permitted.
* If ``REGISTRATION_OPEN`` is both specified and set to
``False``, registration is not permitted.
"""
return getattr(settings, 'REGISTRATION_OPEN', True)
def get_success_url(self, request, user):
return (user.get_absolute_url(), (), {})
I tried the changing the get_success_url function to just return the url I want which is /upload/new but it still redirected me to users/insert username page and gave an error. How do I redirect the user to the upload/new page where the other app resides after registration?
Don't change the code in the registration module. Instead, subclass the RegistrationView, and override the get_success_url method to return the url you want.
from registration.backends.simple.views import RegistrationView
class MyRegistrationView(RegistrationView):
def get_success_url(self, request, user):
return "/upload/new"
Then include your custom registration view in your main urls.py, instead of including the simple backend urls.
urlpatterns = [
# your custom registration view
url(r'^register/$', MyRegistrationView.as_view(), name='registration_register'),
# the rest of the views from the simple backend
url(r'^register/closed/$', TemplateView.as_view(template_name='registration/registration_closed.html'),
name='registration_disallowed'),
url(r'', include('registration.auth_urls')),
]
I am using django_registration 3.1 package. I have posted all 3 files (views.py urls.py forms.py) that are needed to use this package.
To redirect user to a custom url on successfull registration, create a view that subclasses RegistrationView. Pass in a success_url of your choice.
Views.py:
from django_registration.backends.one_step.views import RegistrationView
from django.urls import reverse_lazy
class MyRegistrationView(RegistrationView):
success_url = reverse_lazy('homepage:homepage') # using reverse() will give error
urls.py:
from django.urls import path, include
from django_registration.backends.one_step.views import RegistrationView
from core.forms import CustomUserForm
from .views import MyRegistrationView
app_name = 'core'
urlpatterns = [
# login using rest api
path('api/', include('core.api.urls')),
# register for our custom class
path('auth/register/', MyRegistrationView.as_view(
form_class=CustomUserForm
), name='django_registration_register'),
path('auth/', include('django_registration.backends.one_step.urls')),
path('auth/', include('django.contrib.auth.urls'))
]
forms.py:
from django_registration.forms import RegistrationForm
from core.models import CustomUser
class CustomUserForm(RegistrationForm):
class Meta(RegistrationForm.Meta):
model = CustomUser
You can set SIMPLE_BACKEND_REDIRECT_URL in settings.py.
settings.py
SIMPLE_BACKEND_REDIRECT_URL = '/upload/new'
If you wish, you can modify the following file /usr/local/lib/python2.7/dist-packages/registration/backends/simple/urls.py, changing the path, for example:
Before modifying:
success_url = getattr (settings, 'SIMPLE_BACKEND_REDIRECT_URL', '/'),
After modifying:
success_url = getattr (settings, 'SIMPLE_BACKEND_REDIRECT_URL', '/upload/new'),
Regards.
Diego

Django: Redirect logged in users from login page

I want to set up my site so that if a user hits the /login page and they are already logged in, it will redirect them to the homepage. If they are not logged in then it will display normally. How can I do this since the login code is built into Django?
I'm assuming you're currently using the built-in login view, with
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
or something similar in your urls.
You can write your own login view that wraps the default one. It will check if the user is already logged in (through is_authenticated attribute official documentation) and redirect if he is, and use the default view otherwise.
something like:
from django.contrib.auth.views import login
def custom_login(request):
if request.user.is_authenticated:
return HttpResponseRedirect(...)
else:
return login(request)
and of course change your urls accordingly:
(r'^accounts/login/$', custom_login),
The Django 1.10 way
For Django 1.10, released in August 2016, a new parameter named redirect_authenticated_user was added to the login() function based view present in django.contrib.auth [1].
Example
Suppose we have a Django application with a file named views.py and another file named urls.py. The urls.py file will contain some Python code like this:
#
# Django 1.10 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', auth_views.login, name='login',
kwargs={'redirect_authenticated_user': True}),
url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]
From that file, the relevant part within the urlpatterns variable definition is the following, which uses the already mentioned redirect_authenticated_user parameter with a True value:
url(r'^login/', auth_views.login, name='login',
kwargs={'redirect_authenticated_user': True}),
Take note that the default value of the redirect_authenticated_user parameter is False.
The Django 1.11 way
For Django 1.11, released in April 2017, the LoginView class based view superseded the login() function based view [2], which gives you two options to choose from:
Use the same Django 1.10 way just described before, which is a positive thing because your current code will continue working fine. If you tell Python interpreter to display warnings, by for example running in a console terminal the command python -Wd manage.py runserver in your Django project directory and then going with a web browser to your login page, you would see in that same console terminal a warning message like this:
/usr/local/lib/python3.6/site-packages/django/contrib/auth/views.py:54:
RemovedInDjango21Warning: The login() view is superseded by the
class-based LoginView().
Use the new Django 1.11 way, which will make your code more modern and compatible with future Django releases. With this option, the example given before will now look like the following one:
Example
We again suppose that we have a Django application with a file named views.py and another file named urls.py. The urls.py file will contain some Python code like this:
#
# Django 1.11 way
#
from django.contrib.auth import views as auth_views
from . import views as app_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/',
auth_views.LoginView.as_view(redirect_authenticated_user=True),
name='login'),
url(r'^dashboard/', app_views.Dashboard.as_view(), name='dashboard'),
url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
]
From that file, the relevant part within the urlpatterns variable definition is the following, which again uses the already mentioned redirect_authenticated_user parameter with a True value, but passing it as an argument to the as_view method of the LoginView class:
url(r'^login/',
auth_views.LoginView.as_view(redirect_authenticated_user=False),
name='login'),
Take note that here the default value of the redirect_authenticated_user parameter is also False.
References
[1] Relevant section in Django 1.10 release notes at https://docs.djangoproject.com/en/dev/releases/1.10/#django-contrib-auth
[2] Relevant section in Django 1.11 release notes at https://docs.djangoproject.com/en/1.11/releases/1.11/#django-contrib-auth
anonymous_required decorator
For class based views
Code:
from django.shortcuts import redirect
def anonymous_required(func):
def as_view(request, *args, **kwargs):
redirect_to = kwargs.get('next', settings.LOGIN_REDIRECT_URL )
if request.user.is_authenticated():
return redirect(redirect_to)
response = func(request, *args, **kwargs)
return response
return as_view
Usage:
url(r'^/?$',
anonymous_required(auth_views.login),
),
url(r'^register/?$',
anonymous_required(RegistrationView.as_view()),
name='auth.views.register'
),
# Could be used to decorate the dispatch function of the view instead of the url
For view functions
From http://blog.motane.lu/2010/01/06/django-anonymous_required-decorator/
Code:
from django.http import HttpResponseRedirect
def anonymous_required( view_function, redirect_to = None ):
return AnonymousRequired( view_function, redirect_to )
class AnonymousRequired( object ):
def __init__( self, view_function, redirect_to ):
if redirect_to is None:
from django.conf import settings
redirect_to = settings.LOGIN_REDIRECT_URL
self.view_function = view_function
self.redirect_to = redirect_to
def __call__( self, request, *args, **kwargs ):
if request.user is not None and request.user.is_authenticated():
return HttpResponseRedirect( self.redirect_to )
return self.view_function( request, *args, **kwargs )
Usage:
#anonymous_required
def my_view( request ):
return render_to_response( 'my-view.html' )
For Django 2.x, in your urls.py:
from django.contrib.auth import views as auth_views
from django.urls import path
urlpatterns = [
path('login/', auth_views.LoginView.as_view(redirect_authenticated_user=True), name='login'),
]
Add this decorator above your login view to redirect to /home if a user is already logged in
#user_passes_test(lambda user: not user.username, login_url='/home', redirect_field_name=None)
and don't forget to import the decorator
from django.contrib.auth.decorators import user_passes_test
Since class based views (CBVs) is on the rise. This approach will help you redirect to another url when accessing view for non authenticated users only.
In my example the sign-up page overriding the dispatch() method.
class Signup(CreateView):
template_name = 'sign-up.html'
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
return redirect('path/to/desired/url')
return super().dispatch(*args, **kwargs)
Cheers!
https://docs.djangoproject.com/en/3.1/topics/auth/default/#all-authentication-views
Add the redirect route in settings
LOGIN_URL = 'login'
And in the URLs add redirect_authenticated_user=True to LoginView
path('login/', auth_views.LoginView.as_view(template_name='users/login.html',redirect_authenticated_user=True), name='login')
I know this is a pretty old question, but I'll add my technique in case anyone else needs it:
myproject/myapp/views/misc.py
from django.contrib.auth.views import login as contrib_login, logout as contrib_logout
from django.shortcuts import redirect
from django.conf import settings
def login(request, **kwargs):
if request.user.is_authenticated():
return redirect(settings.LOGIN_REDIRECT_URL)
else:
return contrib_login(request, **kwargs)
logout = contrib_logout
myproject/myapp/urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views.misc',
url(r'^login/$', 'login', {'template_name': 'myapp/login.html'}, name='login'),
url(r'^logout/$', 'logout', {'template_name': 'myapp/logout.html'}, name='logout'),
)
...
Assuming that you are done setting up built-in Django user authentication (and using decorators), add this in your settings.py:
LOGIN_REDIRECT_URL = '/welcome/'
NOTE: '/welcome/' here is the URL of the homepage. It is up to you what to replace it with.
All you have to do is set the "root" url to the homepage view. Since the homepage view is already restricted for logged on users, it'll automatically redirect anonymous users to the login page.
Kepp the url as it is.
And add something like:
(r'^$', 'my_project.my_app.views.homepage'),