Failing functional test on GAE, Django, WebTest - django

I've got a GAE/Django project and I'm trying to make a functional-test enviroment work with WebTest, the project layout is as follows:
/gaeroot
/djangoroot
wsgi.py
urls.py
...
/anapp
urls.py
...
/tests
test_functional.py
wsgi.py (generated by GAE's version of django-admin.py django1.5):
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoroot.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
test_functional.py:
import unittest
import webtest
from djangoroot.wsgi import application
class TestHomePage(unittest.TestCase):
def setUp(self):
self.testapp = webtest.TestApp(application)
def test_get_method_ok(self):
response = self.testapp.get('/path')
self.assertEqual(response.status_int, 200, response)
The failing test message:
Traceback (most recent call last):
...
line 14, in test_get_method_ok
self.assertEqual(response.status_int, 200, response)
AssertionError: Response: 301 MOVED PERMANENTLY
Content-Type: text/html; charset=utf-8
Location: http://localhost:80/path/
Why is throwing a redirect code to the same path, the only thing I can think of is that some code of django is responsible for the redirection because as you can see from the directory tree I have a two level url configuration.
On the other side, why is using port 80? when I test it on the browser it shows an 8080 port, and it shouldn't use a port at all since WebTest it's supposed not to use a port at all since it's testing the WSGI interface right?.
Top level urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^path/', include('djangoroot.anapp.urls')),
)
App level urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns('djangoroot.anapp.views',
url(r'^$', 'home', name='anapp_home'),
)
The browser shows the corret page on the same url, I took the WebTest example from google's support pages, so the problem should be the GAE/Django interop.
Thanks in advance and let me know if you need more info.

The problem seems to be on the django.conf.urls.url function since I tested the root urls.py file and it worked for the root path / with no redirection, but it did redirected me with a path other than the root, I could find nothing that seemed being redirecting my urls on the Django source files.
I found an alternative on the Webtest documentation:
resp = self.testapp.get('/path')
resp = resp.maybe_follow()
with the maybe_follow method you eventually get the final page.
Edit
Finally I found the problem in this line:
response = self.testapp.get('/path')
replace it with this:
response = self.testapp.get('/path/')
It looks like Django redirects the urls to the propper path with the / at the end.

Related

Django: URL Path not found jumps into next app

I have two apps:
backend
shop
I my urls in main app dir:
path('backend/', include('backend.urls')),
path('', include('shop.urls')),
the problem is if I write in my url: localhost:8000/backend/abc which not exist Django jumps over to shop.urls and the app is crashing because it can not find the slug and the query goes in fail.
How can I prevent if I go to the url /backend/somethingwhichnotexist is returning an 404 and not search in other app urls for this folder? I have thought that this is one of the main reason for split the urls in app folders.
Here are some urls from backend/urls.py:
from django.urls import path, re_path
from . import views as backend_views
from django.contrib.auth import views as auth_views
from froala_editor import views
from django.conf.urls import include
urlpatterns = [
path('stamdata/', backend_views.edit_masterdata),
path('praefikser/', backend_views.edit_prefixes),
path('leverandorer/', backend_views.suppliers_view),
path('leverandorer/add', backend_views.add_supplier),
]
handler404 = 'backend.views.page_not_found_view'
shop/urls.py
here the url stops:
path('<slug:category_slug>/<slug:slug_subcategory>/', butik_views.cat_or_article),
normally I don't want that a backend urls switches to frontend view
regards
Christopher.
You you said Django run through all of the URL patterns and stops till it finds its matching URL. SO, what has happen here is that when you type a URL with localhost:8000/backend/abc/ it runs through all the URLS before returning 404 to the client. So, it stops at the URL that support any string with 2 parameters in your case below URL.
path('<slug:category_slug>/<slug:slug_subcategory>/', butik_views.cat_or_article),
To get a 404 by adding a static word in you URL.
path('shop/<slug:category_slug>/<slug:slug_subcategory>/', butik_views.cat_or_article),
or
path('backend/', include('backend.urls')),
path('shop/', include('shop.urls')),
For now I fixed it with
shop/views.py
if category_slug == 'backend':
response = render(
request,
'backend/404.html',
)
response.status_code = 404
return response
else:
until I found another solution. It looks like that the URL dispatcher is working like this:
Django runs through each URL pattern, in order, and stops at the first
one that matches the requested URL, matching against path_info.
So for now I did not found another way.
Edit:
I added this in the end of backend/urls.py:
re_path(r'^.*/$', backend_views.page_not_found_view)
so after all working urls it goes to all other to the 404 view.

Django redirecting from unknown reason

I was working on this app some time back and I have returned and for the life of me cannot see where a redirection is occurring.
From starting the app as below and navigating to the base URL, you can see attempt to reach '/Sites/' url
python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
June 20, 2018 - 16:35:05
Django version 1.11.13, using settings 'SysMan.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Not Found: /Sites/
[20/Jun/2018 16:35:07] "GET /Sites/ HTTP/1.1" 404 2263
The urls file is as below.
from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic.base import RedirectView
from django.contrib.auth import views as auth_views
admin.site.site_header = 'Rio System Management'
admin.site.site_title = 'Rio SysMan admin'
admin.site.index_title = 'SysMan Administration'
urlpatterns = [
url(r'^$', RedirectView.as_view(url='/main/', permanent=True)),
url(r'^admin/', admin.site.urls),
url(r'^main/', include('apps.main.urls')),
url(r'^asnreg/', include('apps.asnreg.urls')),
]
I have run grep against the project folders for Sites with nothing of meaning being returned there.
Manually browsing to the URL's as below get me where I need to be.
http://127.0.0.1:8000/admin/
http://127.0.0.1:8000/main/
http://127.0.0.1:8000/asnreg/
Just can't figure why
http://127.0.0.1:8000/
redirects me to
http://127.0.0.1:8000/Sites/
I have looked at the various views file with nothing obvious there either
I did copy/paste the folders into a new virtenv. Could something be lingering in the DB??

Django 404 pages return 200 status code

I'm going through the Django tutorial and am on part 5: Testing. I run into the problem where I'm using the DetailView and ListView "shortcut" views to factor out code (as suggested by the tutorial), but when a 404 page is displayed, a 200 status code is returned instead. Am I doing something wrong? The tutorial says the status code should be 404.
Thanks!
You need to define the Http header to have a 404 status.
return HttpResponse(content=template.render(context), content_type='text/html; charset=utf-8', status=404)
It is important to inform the search engines that the current page is a 404. Spammers sometimes creates lots of urls that could seem that would lead you to some place, but then serves you another content. They frequently make lots of different addresses serve you almost the exact same content. And because it is not user friendly, most SEO guide lines penalize that. So if you have lots of addresses showing the same pseudo-404 content, it could not look good to the crawling systems from the search websites. Because of that you want to make sure that the page you are serving as a custom 404 has a 404 status.
If you are trying to make a custom 404 page, here it is a good way to go:
Into your application's urls.py add:
# Imports
from django.conf.urls.static import static
from django.conf.urls import handler404
from django.conf.urls import patterns, include, url
from yourapplication import views
##
# Handles the URLS calls
urlpatterns = patterns('',
# url(r'^$', include('app.homepage.urls')),
)
handler404 = views.error404
Into your application's views.py add:
# Imports
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
##
# Handle 404 Errors
# #param request WSGIRequest list with all HTTP Request
def error404(request):
# 1. Load models for this view
#from idgsupply.models import My404Method
# 2. Generate Content for this view
template = loader.get_template('404.htm')
context = Context({
'message': 'All: %s' % request,
})
# 3. Return Template for this view + Data
return HttpResponse(content=template.render(context), content_type='text/html; charset=utf-8', status=404)
The secret is in the last line: status=404
Hope it helped!
I look forward to see the community inputs to this approach. =)
You can
return HttpResponseNotFound(render_to_string('404.html'))
instead.

Custom Django 404 error

I have a 404.html page, but in some cases I want to be able to send a json error message (for 404 and 500, etc.). I read the following page:
https://docs.djangoproject.com/en/dev/topics/http/views/#the-404-page-not-found-view
Is there any sort of example that shows the implementation? I have it in my urls.py but it's not being picked up in the event of an error.
This worked for me:
from django.conf.urls import patterns, include, url
from django.views.static import *
from django.conf import settings
from django.conf.urls.defaults import handler404, handler500
from app.views import error
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'app.views.home', name='home'),
)
handler404 = error.error_handler
handler500 = error.error_handler
You can make it do anything as you wish when going to that controller.
In addition to the previous answer, it is important to say that the views.py should return a HttpResponse with a 404 status in the http header. It is important to inform the search engines that the current page is a 404. Spammers sometimes creates lots of urls that could seem that would lead you to some place, but then serves you another content. They frequently make lots of different addresses serve you almost the exact same content. And because it is not user friendly, most SEO guide lines penalize that. So if you have lots of addresses showing the same pseudo-404 content, it could not look good to the crawling systems from the search websites. Because of that you want to make sure that the page you are serving as a custom 404 has a 404 status. So here it is a good way to go:
Into your application's urls.py add:
# Imports
from django.conf.urls.static import static
from django.conf.urls import handler404
from django.conf.urls import patterns, include, url
from yourapplication import views
##
# Handles the URLS calls
urlpatterns = patterns('',
# url(r'^$', include('app.homepage.urls')),
)
handler404 = views.error404
Into your application's views.py add:
# Imports
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
##
# Handle 404 Errors
# #param request WSGIRequest list with all HTTP Request
def error404(request):
# 1. Load models for this view
#from idgsupply.models import My404Method
# 2. Generate Content for this view
template = loader.get_template('404.htm')
context = Context({
'message': 'All: %s' % request,
})
# 3. Return Template for this view + Data
return HttpResponse(content=template.render(context), content_type='text/html; charset=utf-8', status=404)
The secret is in the last line: status=404
Hope it helped!
I look forward to see the community inputs to this approach. =)
Basics:
To define custom view for handling 404 errors, define in the URL config, a view for handler404, like handler404 = 'views.error404'
Apart from the basics, some things to note about (custom 404 views):
It will be enabled only in Debug=False mode.
And more ignored one, across most answers (and this this stuck my brains out).
The 404 view defaults to
django.views.defaults.page_not_found(request, exception, template_name='404.html')
Notice the parameter exception
This was causing a 404 to 500 redirect from within def get_exception_response(self, request, resolver, status_code, exception) function defined in core.handlers.base since it could not find the parameter exception

Trouble setting up django settings

I'm just learning Django and trying to setup the View and URLconfs (http://djangobook.com/en/2.0/chapter03/).
Inside my project folder "mysite" (/Users/NAME/Desktop/development/Python/djcode/mysite), I have the following two files:
views.py
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world")
and urls.py
from django.conf.urls.defaults import *
from mysite.views import hello
urlpatterns = patterns('',
(r'^hello/$', hello),
)
However, when I run the test server, it shows a 404 page saying:
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^hello/$
The current URL, , didn't match any of these.
I think this has to do with my settings.py not being correct. What do I need to change in the settings.py file to point it to the correct destination?
You have no urlconf pattern corresponding to the root of your webserver. Add ^$ and make it go somewhere.
Looks like the URL you entered when testing it was "http://localhost:8000/". You should enter "http://localhost:8000/hello/" to see the output of the function you made.