Change URL Of Overridden Templates - django

On my website users access their accounts by going to the following address:
http://127.0.0.1:8000/users_area/username/profile
There they will find a button 'change password' (an overridden django template) which will take them to:
http://127.0.0.1:8000/accounts/password/change/
It is very small and I'm probably being too picky but is it possible to keep this overridden template but change its url? I'd instead like the change password url to be something like:
http://127.0.0.1:8000/users_area/username/password/change/
I've tried creating a template within my user's app, copying the 'change password' template content into there, then linking to it rather than to the overridden 'change password' template, but (obviously, in hindsight) it doesn't work.
I'll add as a side note. I actually have two user types, users and powerusers. Each has a unique and rather different 'users_area':
http://127.0.0.1:8000/users_area/username/profile
and
http://127.0.0.1:8000/powerusers_area/username/profile
If I get an answer to my above question I'm actually hoping to apply it to both of my different user types (shouldn't be hard but thought I should mention it).
Thank you.

In case you want to customize them, even have a customized MyUser model, you can still re-use a lot from Django like this
# authentication
path('user_register', user_register_view, name='user_register'),
path('login', login_view, name='login'),
path('logout', logout_view, name='logout'),
path('change_password', change_password_view, name='change_password'),
path('reset_password/',
auth_views.PasswordResetView.as_view(template_name="MyUser/password_reset.html"),
name="reset_password"),
path('reset_password_sent/',
auth_views.PasswordResetDoneView.as_view(template_name="MyUser/password_reset_sent.html"),
name="password_reset_done"),
path('reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name="MyUser/password_reset_form.html"),
name="password_reset_confirm"),
path('reset_password_complete/',
auth_views.PasswordResetCompleteView.as_view(template_name="MyUser/password_reset_done.html"),
name="password_reset_complete"),
path('profile/<username>', profile_view, name='profile'),

You can do something like this
urls.py
from django.contrib.auth import views as auth_views
urlpatterns = i18n_patterns(
# other URLS
path('/users_area/username/password/change/', auth_views.PasswordChangeView.as_view, name='change_password'),
# more URLS from auth?
)

Related

Context not passed to overwritten templates

Django version 3.2.4
I'm trying to change the default index_title, site_header, and site_title used by the admin site. I've tried all the suggestions here, but the login page refuses to use the updated values. In fact, the required context (site_header in the example below) is empty (confirmed by overriding the template and using the {{ debug }} variable as described here) and the "default" value of "Django administration" is being used. A line from the template C:\Program Files\Python38\Lib\site-packages\django\contrib\admin\templates\admin\base_site.html:
<h1 id="site-name">{{ site_header|default:_('Django administration') }} a</h1>
I currently have all three variables overwritten in my app's admin.py file, and the updated values are being used after I've logged in, but it doesn't work on the initial login page:
admin.site.site_header = 'My Site Header'
admin.site.index_title = 'My Index Title'
admin.site.site_title = 'My Site Title'
I can override the base_site.html template and hardcode a value, but I would like to understand why that is necessary and figure out how I can pass some context to that overwritten template. I've tried all the methods of overriding the original context described here to no avail. That includes having a custom admin site which overrides the default admin site. I've also noticed that the each_context method is not being called on the initial login page, but it is called after I have logged in and I'm viewing an admin page.
I think some of the problem may stem from how I have my urlpatterns set up in urls.py. I have it set up like this so the URL displayed in the address bar for a login is the same for both the admin and non-admin portions of the site.
urlpatterns = [
path('', include('my_app.urls')),
path('login', auth_views.LoginView.as_view(template_name='admin/login.html')),
path('login/', auth_views.LoginView.as_view(template_name='admin/login.html')),
path('logout', auth_views.LogoutView.as_view()),
path('logout/', auth_views.LogoutView.as_view()),
path('admin/login', generic_views.RedirectView.as_view(url='/admin', permanent=True, query_string=False)),
path('admin/login/', generic_views.RedirectView.as_view(url='/admin', permanent=True, query_string=False)),
path('admin/logout', auth_views.LogoutView.as_view()),
path('admin/logout/', auth_views.LogoutView.as_view()),
path('admin/', admin.site.urls)
]
I'm also exclusively using the django_auth_ldap.backend.LDAPBackend:
AUTHENTICATION_BACKENDS = [
'django_auth_ldap.backend.LDAPBackend'
]
Any guidance would be appreciated.
I got around my problem by creating the following context processor:
from django.contrib import admin
def global_context(request):
"""
This is intended to be a global context processor. Any templates rendered from views using the
`django.template.RequestContext` context (the default context used by generic views) will have this context
available to them.
"""
context = {
'index_title': admin.site.index_title,
'site_header': admin.site.site_header,
'site_title': admin.site.site_title
}
return context
This in conjunction with setting admin.site.index_title, admin.site.site_header, and admin.site.site_title to the desired values in admin.py got things working as expected.

how to change the Django password reset email style and content

So I'm using the built-in Django password reset system. It works fine, but I'm not satisfied with the email sent to the users. I want to change all of it, from styles to texts. But how am I supposed to do that? I have read some solutions here, but they are more confusing than being helpful.
You can edit the existing email here: <projectName>/lib/python/site-packages/django/contrib/admin/templates/registration/password_reset_email.html
Or you can create an new folder called registration and add the templates to it to create your own:
password_reset_form.html
password_reset_subject.txt
password_reset_email.html
password_reset_done.html
password_reset_confirm.html
password_reset_complete.html
and then include all auth views to your projets url's:
urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]

Django - Retrieve url origin from view - multiple urls to 1 view

I have several urls mapping to one view. Inside the url, I would like to know the url origin? It is to avoid writing multiple views (DRY).
urlpatterns = [
path('path1/', views.IndexView.as_view(), name='index'),
path('path2/', views.IndexView.as_view(), name='index')
]
class IndexView(generic.ListView):
url_origin = ... #would like path1 or path2
I looked for 'reverse' but it does not seem to be a solution to my problem. It returns an error.
reverse('index')
Thank you in advance
You can obtain the original path with request.path [Django-doc] (so in a view function for a class-based view, you can access this with self.request.path.
You can however fix this, for example by providing an extra parameter, like:
urlpatterns = [
path('path1/', views.IndexView.as_view(), name='index1', kwargs={'through': 'path1'}),
path('path2/', views.IndexView.as_view(), name='index2', kwargs={'through': 'path2'})
]
Then you can inspect the self.kwargs['through'] parameter in your class-based view.
Note that you better give the different paths a different name, since otherwise, it will indeed raise an error. By giving these as name 'index1' and 'index2', you can simply use reverse('index1'), and it is not ambiguous to what URL it should redirect.

Django permissions checks at urlconf level?

I've got a django app that has it's own urlconf included into the main one. Every page in this app is protected by a separate set of perms not granted to normal users. Think employees work view as opposed to users' profiles etc.
I'm using classed based views, so right now I've got the landing view's dispatch() checking perms, but with this method I'm going to have to do that for every view. That just isn't DRY.
So my options as I see them are:
Create a mixin that specifically checks for this permission
manually check using dispatch() in each view
Somehow check at the url level
Is there any way to set a permission requirement on the entire url inclusion? They all currently have login_required() on.
Easy!
from django.contrib.auth.decorators import login_required
urlpatterns = patterns('',
url(r'^foo/', login_required(include('foo.urls'))),
)
Update
You want to check user permissions, not user authentication. Easy too:
from django.contrib.auth.decorators import user_passes_test
urlpatterns = patterns('',
url(r'^foo/', user_passes_test(lambda u: u.has_perm('perm'))(include('foo.urls'))),
)

Django password reset stuck in loop

I am trying to add a user reg system to my Django site. Obviously, I want to use the built-in auth views and forms. I am going about implementing the auth password reset process. It works fine up to sending the email, but then does not redirect properly. The end result is the password reset done email being sent over and over and over. I am overriding the templates, but nothing else, right now all they have is:
{{form.As_p}}
I have changed my urls.py to use the auth.views as such:
from django.contrib.auth import views as auth_views
(r'^account/forgot/$',
auth_views.password_reset,
{'template_name': 'registration/password_reset.html',
'post_reset_redirect':'/account/password-reset-done'}
),
(r'^account/password-reset-done/$',
auth_views.password_reset_done,
{'template_name': 'registration/password_reset_done.html'}
),
It looks to me as though you need a trailing slash on the post_reset_redirect url. Have you tried that? At the moment, /account/password-reset-done won't match r'^account/password-reset-done/$' because the / in that is compulsory.
See example request 4 in the Django url dispatcher documentation: https://docs.djangoproject.com/en/dev/topics/http/urls/#example