Catch-all view break URL patterns in Django - python

def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile", self.admin_view(self.profile_view))]
return urls + url_patterns
The above method cause the catch-all view to break URL patterns which I route after the admin URLs and cause the following error/exception:
Page not found (404) Request Method: GET Request
URL: http://127.0.0.1:8000/admin/admin_profile/ Raised
by: django.contrib.admin.sites.catch_all_view
But this only happen when
final_catch_all_view = True
in
django.contrib.admin.sites.catch_all_view
When setting
final_catch_all_view = False
No error or exception is made, everything went fine.
Now my question is how can make the function work when
final_catch_all_view = True
And this is what docs say about catch_all view:
> The new admin catch-all view will break URL patterns routed after the
> admin URLs and matching the admin URL prefix. You can either adjust
> your URL ordering or, if necessary, set AdminSite.final_catch_all_view
> to False, disabling the catch-all view. See What’s new in Django 3.2
> for more details.
Class that urls are appended for:
from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path
class BookrAdmin(admin.AdminSite):
site_header = "Bookr Administration"
logout_template = "admin/logout.html"
def profile_view(self, request):
request.current_app = self.name
context = self.each_context(request)
return TemplateResponse(request, "admin/admin_profile.html", context)
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile", self.admin_view(self.profile_view))]
return url_patterns + urls
urls.py:
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from reviews import views
urlpatterns = [
path('accounts/', include(('django.contrib.auth.urls', 'auth'), namespace='accounts')),
path('accounts/profile/', views.profile, name='profile'),
path('admin/', admin.site.urls),
path('', include('reviews.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

The docs seem to indicate that you need to specify your custom URLs before the django admin URLs. In your get_urls override function, you're appending rather than prepending the custom url. Try the following:
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile", self.admin_view(self.profile_view))]
return url_patterns + urls

Related

Reverse for 'fleet' not found. 'fleet' is not a valid view function or pattern name

I am getting the above error when I try to access the landing page.
What am I missing?
Traceback
NoReverseMatch at /
Reverse for 'fleet' not found. 'fleet' is not a valid view function or pattern name.
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 2.2.6
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'fleet' not found. 'fleet' is not a valid view function or pattern name.
Here is the base.html code
<button>
` Fleet Admin
</button>
and below is the app urls.py file
from django.urls import path
from .admin import fleet_admin_site
app_name = 'trucks'
urlpatterns = [
path('fleet/', fleet_admin_site.urls, name="fleet"),
]
and the main urls.py file
from django.contrib import admin
from django.urls import path, include, reverse
from django.views.generic import TemplateView
urlpatterns = [
path('admin/', include('workers.urls')),
path('admin/', include('trucks.urls')),
path('', TemplateView.as_view(template_name='base.html')),
]
admin.py file where I extend the AdminSite
class FleetAdminSite(admin.AdminSite):
site_header = ''
site_title = ''
index_title = ''
fleet_admin_site = FleetAdminSite(name='fleet_admin')
by seeing your code
you need to add method or class not any extension
path('fleet/', fleet_admin_site.urls, name="fleet"),
path(route, view, kwargs=None, name=None)
refer this
You are including the fleet admin with:
urlpatterns = [
path('fleet/', fleet_admin_site.urls, name="fleet"),
]
You can't do {% url 'trucks:fleet' %} to reverse fleet_admin_site.urls. You need to reverse a particular admin URL.
For example, to reverse the index, you would do:
{% 'trucks:fleet_admin:index' %}
In the above, you use trucks because you have app_name = 'trucks' in the urls.py, fleet_admin because that is the namespace in fleet_admin_site = FleetAdminSite(name='fleet_admin'), and index because that's the view you want to reverse.
Finally, the name in your path() doesn't have any effect, so I would remove it.
urlpatterns = [
path('fleet/', fleet_admin_site.urls),
]

html file urls is not accessible in django

register.html is not accessible on 'register/' url
tried changing url to '' and webpage is accessible but not on 'register/'
projects urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('login/',include('login.urls')),
path('admin/', admin.site.urls),
]
apps urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.indexView, name = "home"),
path('dashboard/', views.dashboardView, name="dashboard"),
#path('login/',),
path('register/',views.registerView, name="register_url"),
#path('logout/',),
]
views.py
from django.shortcuts import render
def indexView(request):
return render(request,'index.html')
def dashboardView(request):
return render(request,'dashboard.html')
def registerView(request):
return render(request,'register.html')
templates/register.html
Either you type login/ before evry URL pattern of apps urls.py file while testing URL.
or
You should include url mapping of apps urls.py in main urls.py
This might help you.
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('',include('apps.urls')), #put you app name here
path('admin/', admin.site.urls),
]
apps urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.indexView, name = "home"),
path('dashboard/', views.dashboardView, name="dashboard"),
path('register/',views.registerView, name="register_url"),
]
This will work and you can add login/ url mapping inside the apps urls.py.
This type of flow will make it easy to understand .
Use url_name for URL calling:
{% url 'register_url' %}
This will directly search for 'register_url' in the project and will return the path.
url_name must be unique so make sure your url_name is uniquely defined.

Using django-cas-ng to authenticate on admin site

I'm using django-cas-ng framework to authenticate users. The main problem is that the admin page still uses the default login view.
Methods used this far:
1.- Using env var
From docs:
CAS_ADMIN_PREFIX: The URL prefix of the Django administration site. If undefined, the CAS middleware will check the view being rendered to see if it lives in django.contrib.admin.views.
2.- Redirecting url on app/urls.py:
url(r'^arta/admin/login$', django_cas_ng.views.login, name='cas_ng_login')
Everything is just ignored and the admin login form is shown.
The goal of this is to only authenticate with CAS and redirect the current /app/admin/login to CAS
If anyone is interested in the answer, the solution was overriding AdminSite. Django admin module overrides it's own url redirects, so editing them on /app/urls.py was useless.
Creating an /app/admin.py and extending AdminSite like:
from django.contrib.admin import AdminSite
from functools import update_wrapper
from django.urls import NoReverseMatch, reverse
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.http import Http404, HttpResponseRedirect
import django_cas_ng.views
class Admin(AdminSite):
def admin_view(self, view, cacheable=False):
"""
Decorator to create an admin view attached to this ``AdminSite``. This
wraps the view and provides permission checking by calling
``self.has_permission``.
You'll want to use this from within ``AdminSite.get_urls()``:
class MyAdminSite(AdminSite):
def get_urls(self):
from django.conf.urls import url
urls = super(MyAdminSite, self).get_urls()
urls += [
url(r'^my_view/$', self.admin_view(some_view))
]
return urls
By default, admin_views are marked non-cacheable using the
``never_cache`` decorator. If the view can be safely cached, set
cacheable=True.
"""
def inner(request, *args, **kwargs):
if not self.has_permission(request):
if request.path == reverse('cas_ng_logout', current_app=self.name):
index_path = reverse('admin:index', current_app=self.name)
return HttpResponseRedirect(index_path)
# Inner import to prevent django.contrib.admin (app) from
# importing django.contrib.auth.models.User (unrelated model).
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
request.get_full_path(),
reverse('cas_ng_login', current_app=self.name)
)
return view(request, *args, **kwargs)
if not cacheable:
inner = never_cache(inner)
# We add csrf_protect here so this function can be used as a utility
# function for any view, without having to repeat 'csrf_protect'.
if not getattr(view, 'csrf_exempt', False):
inner = csrf_protect(inner)
return update_wrapper(inner, view)
def get_urls(self):
from django.conf.urls import url, include
# Since this module gets imported in the application's root package,
# it cannot import models from other applications at the module level,
# and django.contrib.contenttypes.views imports ContentType.
from django.contrib.contenttypes import views as contenttype_views
def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)
wrapper.admin_site = self
return update_wrapper(wrapper, view)
# Admin-site-wide views.
urlpatterns = [
url(r'^$', wrap(self.index), name='index'),
url(r'^login/$', django_cas_ng.views.login, name='login'),
url(r'^logout/$', django_cas_ng.views.logout, name='logout'),
url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True),
name='password_change_done'),
url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut),
name='view_on_site'),
]
# Add in each model's views, and create a list of valid URLS for the
# app_index
valid_app_labels = []
for model, model_admin in self._registry.items():
urlpatterns += [
url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
]
if model._meta.app_label not in valid_app_labels:
valid_app_labels.append(model._meta.app_label)
# If there were ModelAdmins registered, we should have a list of app
# labels for which we need to allow access to the app_index view,
if valid_app_labels:
regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
urlpatterns += [
url(regex, wrap(self.app_index), name='app_list'),
]
return urlpatterns
site = Admin()
Then you override the methods that you want, in this case were admin_view and get_urls
The interesting lines are:
→ admin_view
if request.path == reverse('cas_ng_logout', current_app=self.name):
----
reverse('cas_ng_login', current_app=self.name)
→ get_urls
url(r'^login/$', django_cas_ng.views.login, name='login'),
url(r'^logout/$', django_cas_ng.views.logout, name='logout')
That will let you redirect the login and logout steps into CAS
For being now (April, 2022), we can use builtin middleware of django-cas-ng (v4.x) as below:
MIDDLEWARE_CLASSES = (
...
'django_cas_ng.middleware.CASMiddleware',
...
)
You may add these url pattern in url.py as well, don't change the url name.
urlpatterns = [
...
path('accounts/login/', cas_ng_views.LoginView.as_view(), name='cas_ng_login'),
path('accounts/logout/', cas_ng_views.LogoutView.as_view(), name='cas_ng_logout'),
path('accounts/callback/',cas_ng_views.CallbackView.as_view(), name='cas_ng_proxy_callback'),
...
]

Django - registration login.html as index

My app is hosted on shezankazi.pythonanywhere.com
When I open this link I get to index.html. However I would like to open login.html directly as occurs when I choose "Anmelden" at the index page. Herefore I require assistance
This is my views.py
def index(request):
return render(request, 'crm/index.html')
class MyRegistrationView(RegistrationView):
def get_success_url(self, request, user):
return '/crm/'
This is my app/urls.py
from django.conf.urls import url
from django.conf.urls import include
from django.contrib import admin
from crm import views as crm_views
from person import views as person_views
urlpatterns = [
url(r'^$', crm_views.index, name='index'),
url(r'^crm/', include('crm.urls')),
...
]
And this is my crm/urls.py
from django.conf.urls import url
from crm import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^dashboard/', views.dashboard, name='dashboard'),
]
And this is the end of my settings.py:
# If True, users can register
REGISTRATION_OPEN = False
# One-week activation window; you may, of course, use a different value.
ACCOUNT_ACTIVATION_DAYS = 7
# If True, the user will be automatically logged in.
REGISTRATION_AUTO_LOGIN = False
# The page you want users to arrive at after they successful log in
LOGIN_REDIRECT_URL = '/crm/dashboard/'
# The page users are directed to if they are not logged in,
# and are trying to access pages requiring authentication
LOGIN_URL = '/accounts/login/'
# The page users are directed to upon logging out
LOGOUT_REDIRECT_URL = '/accounts/login'
At first I changed the index view to render registration/login.html but then whenever I enter my credentials, the login page loads again instead of redirecting me to the dashboard.
change the order of the following two lines:
url(r'^$', views.index, name='index'),
url(r'^dashboard/', views.dashboard, name='dashboard'),,
and change the following:
return '/crm/dashboard/'

Django views and URl's

I'm having a problem with the way my URL's look in Django. I have a view like this:
def updatetext(request, fb_id):
Account.objects.filter(id=fb_id).update(display_hashtag=request.POST['hashtag'])
fb = get_object_or_404(Account, pk=fb_id)
return render(request, 'myapp/account.html', {
'success_message': "Success: Settings updated.",
'user': fb
})
When a user clicks on the URL to update the text they are then redirected to the account page but the URL then looks like 'account/updatetext/'. I would like it just be 'account/'.
How would I do this in Django. What would I use in place of render that would still allow me to pass request, 'success_message' and 'user' into the returned page but to not contain the 'updatetext' within the URL?
[edit]
The urls.py file looks like this:
from django.conf.urls import patterns, url
from myapp import views
urlpatterns = patterns('',
url(r'^home/$', views.index, name='index'),
url(r'^(?P<fb_id>\d+)/$', views.account, name='account'),
url(r'^(?P<fb_id>\d+)/updatetext/$', views.updatetext, name='updatetext'),
url(r'^(?P<fb_id>\d+)/updatepages/$', views.updatepages, name='updatepages'),
url(r'^login/$', views.user_login, name='login'),
url(r'^logout/$', views.user_logout, name='logout'),
url(r'^admin/$', views.useradmin, name='admin'),
)
You need to actually redirect the user to '/account/'. Rather than returning a call to render you can do the following:
from django.http import HttpResponseRedirect
def updatetext(request, fb_id):
Account.objects.filter(id=fb_id).update(display_hashtag=request.POST['hashtag'])
fb = get_object_or_404(Account, pk=fb_id)
return HttpResponseRedirect(reverse('account', kwargs={"fb_id": fb_id}))
However, it would be better to pass in a call to reverse into the HttpResponseRedirect constructor, but since I don't know your urls.py I just wrote the relative url.

Categories