How do you pass 'exception' argument to 403 view? - django

**Edit: Of course, it dawns on me that this doesn't have anything to do with the UserPassesTextMixin, because this error pops up when trying to visit the 403 page directly. Still not sure what to make of it though.
I'm attempting to use UserPassesTestMixin to check which model's edit view is being requested and run a test specific to that model to see if the user should have access. Nothing is working yet, I'm just trying to get a feel for how this mixin operates. Upon returning false in the test_func, the view tries to redirect to /403/, but I get the below error.
TypeError at /403/
permission_denied() missing 1 required positional argument: 'exception'
view
class DeviceUpdate(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Device
template_name_suffix = '_update_form'
form_class = DeviceUpdateForm
def test_func(self):
return edit_permission_test(self.get_object())
...
perms.py
def edit_permission_test(model_object):
possible_models = ['Device',]
if isinstance(model_object, Device):
print('This is a Device model object')
return True
else:
print('This doesnt look like a Device model object')
return False
I cant seem to find anything out there on the interwebs that helps with this error.

I think this issue just had to do with how the url patterns were configured for local development. Previously my main urls.py looked like this:
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name="home"),
...
# Your stuff: custom urls includes go here
url(r'^devices/', include('auto_toner.urls', namespace='auto_toner', app_name='auto_toner'), name="devices"),
url(r'^400/$', default_views.bad_request),
url(r'^403/$', default_views.permission_denied),
url(r'^404/$', default_views.page_not_found),
url(r'^500/$', default_views.server_error),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I changed the URLs to include kwargs in the pattern if settings.DEBUG was True.
if settings.DEBUG:
# This allows the error pages to be debugged during development, just visit
# these url in browser to see how these error pages look like.
urlpatterns += [
url(r'^400/$', default_views.bad_request, kwargs={'exception': Exception('Bad Request!')}),
url(r'^403/$', default_views.permission_denied, kwargs={'exception': Exception('Permission Denied')}),
url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception('Page not Found')}),
url(r'^500/$', default_views.server_error),
]
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]

Related

Page not found (404), The empty path didn’t match any of these [duplicate]

Very basic question and I was surprised I wasn't able to find an answer. I'm just starting looking at django and did an out-of-box intallation. Created a project and created an app.
The default content of urls.py is very simple:
urlpatterns = [
path('admin/', admin.site.urls),
]
And if I open the django site home page, I get the content with a rocket picture. However, like I said, I have created another app in the project, let's say called 'bboard'. And I have created a simple 'hello world' function in bboard/views.py
def index(request):
return HttpResponse('Hello world')
to enable it for access through browser, I have modified the original urls.py file in the following way:
from bboard.views import index
urlpatterns = [
path('admin/', admin.site.urls),
path('bboard/', index),
]
This way I can access localhost:port/admin and localhost:port/bboard URLs, but if I try to open the home page with localhost:port now, I get Page not found error.
Using the URLconf defined in samplesite.urls, Django tried these URL patterns, in this order:
admin/
bboard/
The empty path didn't match any of these.
if I comment out the second item in urlpatterns list, everything works. So why does the additional pattern impact this and what needs to be done to fix it?
You need to add an empty url in root urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('bboard.urls'))
]
Before you add your own routes Django will serve the default home page at the '/' url. After you add your own route config, django no longer serves up its default sample home page.
From the django's django/views/debug.py:
def technical_404_response(request, exception):
"""Create a technical 404 error response. `exception` is the Http404."""
try:
error_url = exception.args[0]['path']
except (IndexError, TypeError, KeyError):
error_url = request.path_info[1:] # Trim leading slash
try:
tried = exception.args[0]['tried']
except (IndexError, TypeError, KeyError):
tried = []
else:
if (not tried or ( # empty URLconf
request.path == '/' and
len(tried) == 1 and # default URLconf
len(tried[0]) == 1 and
getattr(tried[0][0], 'app_name', '') == getattr(tried[0][0], 'namespace', '') == 'admin'
)):
return default_urlconf(request)
Note the final else block that returns a default_urlconf if the only url path included is the admin path and the requested url is /. This default_urlconf is the sample Rocket page you mentioned. As soon as you add any of your own routes the if statement in the else block will be false so the default_urlconf is not returned and instead falls through to the normal 404 handler.
Here's the default_urlconf
def default_urlconf(request):
"""Create an empty URLconf 404 error response."""
with Path(CURRENT_DIR, 'templates', 'default_urlconf.html').open() as fh:
t = DEBUG_ENGINE.from_string(fh.read())
c = Context({
'version': get_docs_version(),
})
return HttpResponse(t.render(c), content_type='text/html')
The other reason that you might be getting this error is because
You haven't passed an empty URL inside your application URL
Kindly (this is a simple but a very crucial one) check for typos

Cannot understand error when url is changed in django. It throws '404'

When I first created the urls with 'pk' they worked fine.
But when I use 'slug' for lookup, when I change the url it throws 404.
from django.urls import path
from .views import (ProductListView, ProductDetailView,
ProductFeaturedListView, ProductFeaturedDetailView)
app_name = 'products'
urlpatterns = [
path('', ProductListView.as_view(),
name='list'),
path('detail/<str:slug>/', ProductDetailView.as_view(),
name='detail'),
path('featured/', ProductFeaturedListView.as_view(),
name='featured-list'),
path('featured/<str:slug>/', ProductFeaturedDetailView.as_view(),
name='featured-detail')
]
Now when I change the 'product-detail' url, the feature url throws error which is irrelevant. And it says that this particular view is causing it. But the view has no relation with 'featured-product-list' url.
from .views import (ProductListView, ProductDetailView,
ProductFeaturedListView, ProductFeaturedDetailView)
app_name = 'products'
urlpatterns = [
path('', ProductListView.as_view(),
name='list'),
path('<str:slug>/', ProductDetailView.as_view(),
name='detail'),
path('featured/', ProductFeaturedListView.as_view(),
name='featured-list'),
path('featured/<str:slug>/', ProductFeaturedDetailView.as_view(),
name='featured-detail')
]
error
On diagnosing it I find that it is trying to pass 'featured' as a slug, which is out of my logic.
Please help me to find what is causing this issue.
here is the detailed error
class ProductDetailView(DetailView):
template_name = 'products/product_detail.html'
def get_object(self):
slug = self.kwargs.get('slug')
try:
instance = Product.objects.all().get(slug=slug)
except Product.DoesNotExist:
raise Http404('Not Found...')
except Exception:
raise Http404('huh?')
return instance

Django routing - The empty path didn't match any of these

Very basic question and I was surprised I wasn't able to find an answer. I'm just starting looking at django and did an out-of-box intallation. Created a project and created an app.
The default content of urls.py is very simple:
urlpatterns = [
path('admin/', admin.site.urls),
]
And if I open the django site home page, I get the content with a rocket picture. However, like I said, I have created another app in the project, let's say called 'bboard'. And I have created a simple 'hello world' function in bboard/views.py
def index(request):
return HttpResponse('Hello world')
to enable it for access through browser, I have modified the original urls.py file in the following way:
from bboard.views import index
urlpatterns = [
path('admin/', admin.site.urls),
path('bboard/', index),
]
This way I can access localhost:port/admin and localhost:port/bboard URLs, but if I try to open the home page with localhost:port now, I get Page not found error.
Using the URLconf defined in samplesite.urls, Django tried these URL patterns, in this order:
admin/
bboard/
The empty path didn't match any of these.
if I comment out the second item in urlpatterns list, everything works. So why does the additional pattern impact this and what needs to be done to fix it?
You need to add an empty url in root urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('bboard.urls'))
]
Before you add your own routes Django will serve the default home page at the '/' url. After you add your own route config, django no longer serves up its default sample home page.
From the django's django/views/debug.py:
def technical_404_response(request, exception):
"""Create a technical 404 error response. `exception` is the Http404."""
try:
error_url = exception.args[0]['path']
except (IndexError, TypeError, KeyError):
error_url = request.path_info[1:] # Trim leading slash
try:
tried = exception.args[0]['tried']
except (IndexError, TypeError, KeyError):
tried = []
else:
if (not tried or ( # empty URLconf
request.path == '/' and
len(tried) == 1 and # default URLconf
len(tried[0]) == 1 and
getattr(tried[0][0], 'app_name', '') == getattr(tried[0][0], 'namespace', '') == 'admin'
)):
return default_urlconf(request)
Note the final else block that returns a default_urlconf if the only url path included is the admin path and the requested url is /. This default_urlconf is the sample Rocket page you mentioned. As soon as you add any of your own routes the if statement in the else block will be false so the default_urlconf is not returned and instead falls through to the normal 404 handler.
Here's the default_urlconf
def default_urlconf(request):
"""Create an empty URLconf 404 error response."""
with Path(CURRENT_DIR, 'templates', 'default_urlconf.html').open() as fh:
t = DEBUG_ENGINE.from_string(fh.read())
c = Context({
'version': get_docs_version(),
})
return HttpResponse(t.render(c), content_type='text/html')
The other reason that you might be getting this error is because
You haven't passed an empty URL inside your application URL
Kindly (this is a simple but a very crucial one) check for typos

Invalid syntax when trying to create custom http errors

I'm trying to make custom http error pages. And as usual the django docs are really hard to understand.
I'm trying my best to follow this doc: https://docs.djangoproject.com/en/2.1/topics/http/views/#customizing-error-views
So I have set DEBUG = False
I have set ALLOWED_HOSTS = ['*']
In my views.py (not inside an app)
def server_error(request, exception):
return render(request, 'mysite/errors/500.html')
And in my urls.py (not inside an app), after all paths.
urlpatterns = [
path('', views.index, name='index'),
.......etc
handler500 = 'mysite.views.server_error'
]
When I run my server, I get instant error on handler500 in urls.py.
handler500 = 'mysite.views.server_error'
^
SyntaxError: invalid syntax
I also made a simple '500.html' under 'templates/errors'.
I have tried with importing handler, even though I read that I should not.
I tried with removing 'mysite' in location for view etc.
I can't seem to find anything about this SyntaxError on my handler?
Put handler500 = 'mysite.views.server_error' outside of urlpatterns at file level.
urlpatterns = [
path('', views.index, name='index'),
.......
]
handler500 = 'mysite.views.server_error'
Also add 500 response status in the error view
def server_error(request):
return render(request, 'mysite/errors/500.html', status=500)

Django URL regex with variables

Was hoping someone could point me in the right direction with this. I've tried nearly everything I can think of, but I can't seem to get it to work. I've got a set of URLs I'd like to match in Django:
www.something.com/django/tabs/
www.something.com/django/tabs/?id=1
Basically, I want to make it so that when you just visit www.something.com/django/tabs/ it takes you to a splash page where you can browse through stuff. When you visit the second URL however, it takes you to a specific page which you can browse to from the first URL. This page is rendered based on an object in the database, which is why the id number is there. I've tried to account for this in the URL regex, but nothing I try seems to work. They all just take me to the main page.
This is what I have in urls.py within the main site folder:
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', include("tabs.urls")),
]
and within urls.py in the app's folder:
urlpatterns = [
url(r'\?id=\d+$', tab),
url(r'^$', alltabs)
]
Would anyone be so kind as to point me in the right direction? Thanks in advance!
You are not following the right approach here. Query paramers are used to change the behaviour of the page slightly. Like a added filter, search query etc.
What i would suggest is you have only one view and render different templates based on query parameters in the view.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^tabs/', alltabs),
]
In your alltab views you can have something like this.
def alltabs(request):
if request.GET.get("id"):
id = request.GET.get("id")
your_object = MyModel.objects.get(id=id)
return render_to_response("tab.html", {"object":your_object})
return render_to_response("alltab.html")
Hope this helps
This is not the preferred 'django way' of defining urls patterns, I would say:-)
In the spirit of django would be something like
www.something.com/django/tabs/
www.something.com/django/tabs/1/
....
www.something.com/django/tabs/4/
and for this you define your url patterns within the app for example this way
tabs/urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /tabs/
url(r'^$', views.index, name='index'),
# ex: /tabs/5/
url(r'^(?P<tab_id>[0-9]+)/$', views.detail, name='detail'),
# ex: /tabs/5/results/
url(r'^(?P<tab_id>[0-9]+)/results/$', views.results, name='results'),
]
and something similar in your views
tabs/views.py:
from django.shortcuts import get_object_or_404, render
from tabs.models import Tab
def index(request):
return render(request, 'tabs/index.html')
def detail(request, tab_id):
tab = get_object_or_404(Tab, pk=tab_id)
return render(request, 'tabs/detail.html', {'tab': tab})
...
You can follow this django tutorial for more details: