Custom login URL in django - django

I am a newbie in django and I was experting different options in Django. I have created a class based view which requires user authentication to view the web page. I am using the inbuilt LoginView.
When the url pattern is specified as follows
url(r'^login/', auth_views.LoginView.as_view(),name='login'),
it is correctly redirected to login page.
But when I give
url(r'^restaurant/login/', auth_views.LoginView.as_view(),name='login'),
I get a 404 when trying to access the page that requires user authentication.
But when I manually go to that url in browser, it works perfectly fine.
Why is that? Shouldn't it both cases work?

It sounds like you need to set LOGIN_URL in your settings:
LOGIN_URL = '/restaurant/login/'
or, it's better to use the URL pattern name, then you don't have to update your settings when you change the login URL
LOGIN_URL = 'login'

Not sure if I'd fully understand your question, just try to give a stupid answer.
Django 2.1.7
use namespace&url name in settings, if you have your own login view just change admin to your url namespace and name your view as 'login'
# settings.py
LOGIN_URL = 'admin:login'
then the login_required decorator will direct you the correct login page.
from django.contrib.auth.decorators import login_required
#login_required()
def month_archive(request, year, month):
production_list = Production.objects.month_archive(year, month)
context = {'production_list': production_list}
return TemplateResponse(request, 'production/production_list.html', context)
If it's a Class Based View, add decorator to urls.py
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', login_required(views.ProductionList.as_view()), name='production-list'),
path('<int:year>/<int:month>/', views.month_archive, name='production-month'),
]

Related

Django LOGIN_REDIRECT_URL does not work with "next" request parameter

Django 1.11.3
The documentation about LOGIN_REDIRECT_URL says that:
The URL where requests are redirected after login when the
contrib.auth.login view gets no next parameter.
I have LOGIN_REDIRECT_URL="some_url" in setting.py
I see "next=" (no value, just the key) in the request url when I login, so I suspect that makes Django to ignore LOGIN_REDIRECT_URL and I end up on Admin default page.
I use default login Django functionality, no custom template or anything. How do I get rid of "next=" in my request when I login (completely, no key) to see if LOGIN_REDIRECT_URL will be actually used (hopefully) ?
That’s expected behavior. Normally you want the user requesting any view requiring login (with the #login_required decorator) to be redirected to that same view after login. This is documented here
Since your view url is empty (the home url) you get next=. It’s quite uncommon to have a login required on the home page, from a user perspective it means you can’t see what you're signing up for.
If you remove the #login_required decorator for your view and just add a login button on your homepage (that goes to the regular LoginView) it will not have the next parameter and your users will be redirected to LOGIN_REDIRECT_URL as expected.
Now, if really want users to have to login on your homepage and be redirected to LOGIN_REDIRECT_URL, you have two options:
Remove the #login_required decorator and do the check and redirect in your view:
from django.conf import settings
def homepage(request):
if not request.user.is_authenticated:
return redirect(settings.LOGIN_URL)
# rest of view code
If you're using class-based views, use the LoginRequiredMixin in your view and handle handle_no_permission() yourself:
from django.contrib.auth.views import redirect_to_login
from django.contrib.auth.mixins import LoginRequiredMixin
class Home(LoginRequiredMixin, View):
def get(self):
# your view code
def handle_no_permission(self):
# pass None to redirect_field_name in order to remove the next param
return redirect_to_login(self.request.get_full_path(), self.get_login_url(), None)
If you are having LOGIN_REDIRECT_URL in your settings.py, then in case you are not giving any next parameter to url, it will go to default url mentioned in LOGIN_REDIRECT_URL.
if LOGIN_REDIRECT_URL = 'some/path/'
https://yourdomain.com/login/ will redirect to 'some/path/'
https://yourdomain.com/login/?next=/override/default/path
will redirect to 'override/default/path'

django-two-factor-auth can't access admin site

I am using django-two-factor-auth for a webapp. I cannot access the admin page.
I know I am entering the correct credentials. When I input incorrect credentials, I get an appropriate error message.
When I input the correct credentials, the page simply reloads with this URL:
http://localhost:8080/account/login/?next=/inveskore/
These are my settings related to two_factor:
LOGIN_URL = 'two_factor:login'
LOGIN_REDIRECT_URL = '/inveskore'
TWO_FACTOR_SMS_GATEWAY = 'two_factor.gateways.twilio.gateway.Twilio'
This is the associated URL path:
path('admin/', admin.site.urls),
According to this, it results from the admin user not having 2FA set.
So, how do you set 2FA for the admin user if you can't access the site?
EDIT:
I took down the 2FA login requirements for the site and then added a phone device. No luck.
I recently ran into this scenario and created this solution based on a comment there:
https://github.com/Bouke/django-two-factor-auth/issues/219#issuecomment-494382380
I subclassed AdminSiteOTPRequired and then specified it as the admin class to use
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.views import redirect_to_login
from django.http import HttpResponseRedirect
from django.shortcuts import resolve_url
from django.urls import reverse
from django.utils.http import is_safe_url
from two_factor.admin import AdminSiteOTPRequired, AdminSiteOTPRequiredMixin
class AdminSiteOTPRequiredMixinRedirSetup(AdminSiteOTPRequired):
def login(self, request, extra_context=None):
redirect_to = request.POST.get(
REDIRECT_FIELD_NAME, request.GET.get(REDIRECT_FIELD_NAME)
)
# For users not yet verified the AdminSiteOTPRequired.has_permission
# will fail. So use the standard admin has_permission check:
# (is_active and is_staff) and then check for verification.
# Go to index if they pass, otherwise make them setup OTP device.
if request.method == "GET" and super(
AdminSiteOTPRequiredMixin, self
).has_permission(request):
# Already logged-in and verified by OTP
if request.user.is_verified():
# User has permission
index_path = reverse("admin:index", current_app=self.name)
else:
# User has permission but no OTP set:
index_path = reverse("two_factor:setup", current_app=self.name)
return HttpResponseRedirect(index_path)
if not redirect_to or not is_safe_url(
url=redirect_to, allowed_hosts=[request.get_host()]
):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
return redirect_to_login(redirect_to)
Then in urls.py:
from django.contrib import admin
admin.site.__class__ = AdminSiteOTPRequiredMixinRedirSetup
I cannot comment yet but the answer above by #saschwarz worked like a charm with Django 2.2 and django-two-factor-auth. The only thing missing from his code is the additional import:
from django.http import HttpResponseRedirect
After that I was able to use this line:
admin.site.__class__ = AdminSiteOTPRequiredMixinRedirSetup
to quickly enforce two factor for admin users.
This is really missing from the docs for django-two-factor-auth... I looked at the documentation for quite a while and couldn't find a clear way to generate a qr code. It's only really demonstrated in the demo app, and not in a very modular way.
The solution from saschewarz didn't solve the problem in my app.
So I found another one where standard admin login is shown.
django-two-factor-auth by default patch your admin urls with function 'patch_admin' from two_factor\admin.py so you always will see your standard site login for admin login.
To solve this you can comment out 2 functions in two_factor\admin.py
def patch_admin()
and
def unpatch_admin()
And comment out in two_factor\apps.py
def ready(self)
And to use two factor authentication in admin site add this code in main urls.py (where is path to admin):
from django_otp.admin import OTPAdminSite
admin.site.__class__ = OTPAdminSite

Redirect to the login URL when user enters default address in Django?

I have this URL which takes user to the login page:
url(r'^login_backend', 'fileupload.backend.login_backend'),
Since the user doesn't want to remember:
http://127.0.0.1:8000/login_backend
I want to redirect http://127.0.0.1:8000 to http://127.0.0.1:8000/login_backend without affecting any other activity. I have this decorator above every view:
#login_required(login_url='/login_backend/')
You can use django generic redirect_to view. Add following in your urls.py
urlpatterns = patterns('django.views.generic.simple',
('^$', 'redirect_to', {'url': 'login_backend/'}),
)

Redirecting to another page after django admin login

I am making a custom administration page in Django. I do not want to reinvent the wheel and thus want to use Django admin login form for the staff to log in and redirect them to /my-url/ afterwards.
However, I can't find the way to redirect user to a custom url after successful login at /admin/.
since I stumbled across the same problem, I noticed the url of the the default login page:
/admin/login/?next=/admin/
so I changed the login page link to
/admin/login/?next=/
to point to the main page
works for the logout page too, nice and simple
I had the same issue.
Instead of redirect after login I used the #staff_member_required decorator
for my view /my-url/ which redirects to the admin login
from django.contrib.admin.views.decorators import staff_member_required
#staff_member_required
def test_list(request):
return HttpResponse('TEST')
If class based views is used check out the method_decorator
The Django auth app comes with a login view which you can hook up to /accounts/login/ or any other url you choose. You can probably use the admin's login template admin/login.html if you don't want to write your own.
By using the login view, the LOGIN_REDIRECT_URL parameter will work. The purpose of the /admin/ page is to display the admin index. I would avoid trying to use it as the login page.
Set LOGIN_REDIRECT_URL in your settings.py file. Documented here.
If you have ?next= parameter set is not enough to set LOGIN_REDIRECT_URL in you setting.py. You need to also handel this parameter. As say docs (https://docs.djangoproject.com/en/4.1/ref/settings/#login-redirect-url):
LOGIN_REDIRECT_URL
Default: '/accounts/profile/'
The URL or named URL pattern where requests are redirected after login
when the LoginView doesn’t get a next GET parameter.
In my case I just set REDIRECT_FIELD_NAME = "" instead of REDIRECT_FIELD_NAME = "next" in my django.contrib.auth and it works fine.

Pass form to template after registration

I'm using django-registration app to perform registration. After registration (no matter if successful or not), I'd like to return to whatever page the registation app would redirect, but I want to pass a login form to that template.
Something like this:
def register(request):
registered = reg_views.register(request, backend='registration.backends.default.DefaultBackend', template_name='zzz/index.html')
login_form = AuthenticationForm()
return render_to_response(registered, { 'login_form': login_form })
and then in the template have the ussual:
{{ login_form.as_p }}
Here's what I am trying to achieve:
I want to leverage the functionality of the registration app. However, after a (un)successful registration, I need to be able to display the login form on the page. This login form should be passed from the view (DRY principle).
Thanks,
Matyas
urls.py
urlpatterns = patterns('',
(r'^accounts/', include('external.registration.urls')),
)
new urls.py
urlpatterns = patterns('',
(r'^accounts/register', 'point.to.new.view'),
(r'^accounts/', include('external.registration.urls')),
)
With this set, you can copy the register view somewhere on your code from the registration app, and modify it as you please, without having to modify the app it self. The register view is pretty straight forward so you will have no problem making some changes.
You should not be needed to copy any code from register view of django-registration.
Say, you want to handle authentication functionality in your app named accounts
This goes in accounts/views.py
def registration_complete(request):
login_form = AuthenticationForm()
return render_to_response("registration_complete.html", {"login_form": login_form})
accounts/urls.py
url(r'^registration_complete/', 'accounts.views.registration_complete', name='accounts_registration_complete'),
In your template registration_complete.html
{{login_form.as_p}}
Now you are done with registration_complete setup.
register view of django-registration takes a success_url where it redirects after successful registration.
Provide this success_url as the url we created in accounts.
Your urls.py:
urlpatterns = patterns('',
(r'^registration/register/$', 'registration.register', {'backend': 'registration.backends.default.DefaultBackend', 'success_url': 'accounts_registration_complete'}),
(r'^registration/', include('registration.urls')),
)
Now after registration the user will be redirected to a page which contains the login form.