How to use next_page in Django URL path - django

I have two URL class views from django.contrib.auth:
path('login/', auth_views.LoginView.as_view(
template_name='accounts/login/login.html'), name='my_login'),
path('logout/', auth_views.LogoutView.as_view(
template_name='accounts/logout/logout.html', next_page=XXXX), name='my_logout'),
What's the correct syntax to pass to next_page in the LogoutView? E.g.:
next_page='accounts/login/'
next_page='accounts/login/login.html'
next_page=my_login
next_page='my_login'
next_page=reverse_lazy('my_login')

You can pass my_login as value of next_page as per the implementation. Basically its using resolve_url.
path('logout/', auth_views.LogoutView.as_view(next_page='my_login'), name='my_logout'),
But as #WillemVanOnsem said, you don't need to pass template_name as you will be redirecting to my_login url.

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.

Change URL Of Overridden Templates

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?
)

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.

redirect vs reverse django

I have experienced using reverse within get_absolute_url method in the model, but I wish I have an idea about the difference between reverse and redirect, I have tried to search on google about it but there is almost nothing
I don't know what should I write also to convince stack overflow that I don't have any other description
Reverse and redirect have a different meaning. Here is a simple explanation:
reverse in Django is used to find the URL of a given resource. Let's say that you have a blog website and from the main page, you want to provide links to your blog posts. You can of course just hard-code /posts/123/ and just change the ID of your blog post in URL, but that makes it hard to change your URL for the post in the future. That's why Django comes with reverse function. All you need to do is to pass the name of your URL path (defined in your urlpatterns) and Django will find for you the correct URL. It is called reverse because it is a reverse process of determining which view should be called for a given URL (which process is called resolving).
Redirects are not specific to Django or any other web frameworks. Redirect means that for a given URL (or action), the user should be instructed to visit a specific URL. This can be done by sending a special redirect request and from there the browser will handle it for the user, so no user action is required in that process. You can use reverse in redirect process to determine the URL that the user should be redirected to.
GwynBleidD has given you the answer, but there is a reason why you might be getting confused. The Django redirect shortcut accepts arguments in several different forms. One of them is a URLpattern mane, with arguments, that is then passed to reverse to generate the actual URL to redirect to. But that's just a shortcut, to enable a common pattern.
here's an example
app/views
#imports
def indexView(request):
....
return render(request, 'index.html', context)
def loginView(request):
....
return redirect('index')
def articleDetailView(request, id):
....
return redirect(reverse('article-comments', kwargs={'id':id})
def articleCommentsView(request, id):
....
return render(request, 'comment_list.html', context)
proj/urls
#imports
urlpatterns = [
....,
path('', include(app.urls))
]
app/urls
#imports
urlpatterns = [
....,
path('index/', index, name='index'),
path('login/', loginView, name='login'),
path('article/<int:id>/detail', articleDetailView, name='article-detail'),
path('article/<int:id>/comments/',articleCommentsView, name='article-comments')
....,
]
For loginView redirect will return url as-is i.e. 'index' which will be appended to base(project) urlpatterns. Here redirect(reverse('index')) will also work since kwargs is None by default for reverse function and 'index' view doesn't require any kwarg. It returns '/index/' which is passed to redirect(which again will be appended to base urls).
One thing to note is that reverse is used to make complete url - needed for redirect - that is shown in 'articleDetailview'.
The most basic difference between the two is :
Redirect Method will redirect you to a specific route in General.
Reverse Method will return the complete URL to that route as a String.

django print referred url in view

In the following code how will i know there are two hyper links which are pointing to the same view.My question is in view how will i know which link the user is referring to? how can i get the referred url context in the view
JS:
window.location = "/project/server/fserver";
window.location = "/project/server/";
urls:
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^fserver/$', views.IndexView.as_view(), name='index'),
views
class IndexView(tables.DataTableView, VolumeTableMixIn):
table_class = project_tables.VolumesTable
template_name = 'project/server/index.html'
def get_data(self):
print "In get data==============="
.......
https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.path
def get_data(self):
print self.request.path
...you could also do this with a single url pattern
url(r'^(?:fserver/)?$', views.IndexView.as_view(), name='index'),
or capturing as a kwarg passed to the view:
url(r'^((?P<page>fserver)/)?$', views.IndexView.as_view(), name='index'),
An Alternate way is:
-> Add a class variable in you view to store the url name:
class IndexView(tables.DataTableView, VolumeTableMixIn):
view_url_name = 'index'
........
-> Change the URL definition to following:
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^fserver/$', views.IndexView.as_view(view_url_name='index_fserver'), name='index_fserver'),
Also, this will help you get the url in more django-ish manner e.g. reverse(view_url_name)
Note: Two different urls should never be of the same name, as this creates ambiguity & After all the first matching name will be picked by Django so its of no use either.