Django + mod_wsgi: Why is empty url pattern always evaluated? - python

I have a very simple Django project with an url-pattern, similar to this one:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^log/', include('apps.logging.urls')),
url(r'^OPTION1/?', index, name="index"),
url(r'^OPTION2/?', index, name="index"),
url(r'^$', index, name="index"),
url(r'^.+/?', RedirectView.as_view(url="/", permanent=False)),
)
So essentially, I want the index view to be rendered, when the url is either /OPTION1, /OPTION2 or /. I also tried to put this logic into one single regular expression, but I always ended up with the same problem:
As soon as I'm working in production mode on an actual server, the emtpy url patter (^$), gets always evaluated in addition to the normal one. So if someone navigates to /OPTION1, the index view will actually called twice, once with / and once with /OPTION1 as path.
As soon as I comment out the empty url patter everything works fine. I also have no redirects (except the one that you see in the url pattern, but I can comment it out and the problem persists), that could cause this problem and the status code returned is always 200.
So has someone any idea what's going on?

u can use this to redirect to ur home page upon xyz option:
url(r'^/(?P<slug>[^\.]+)/$', anotherIndex),
and inside the view u can use this:
from django.shortcuts import HttpResponseRedirect
def anotherIndex(request, slug):
redirect_url = "/"
if slug == "OPTION1":
redirect_url = "/OPTION1"
elif slug == "OPTION2":
redirect_url = "/OPTION1"
return HttpResponseRedirect(redirect_url)
I hope it helps

Related

Avoid Django form being resubmitted by using HttpResponseRedirect

My views.py runs code fine when I press a button on my HTML page, views.py:
def start_or_end_fast(request):
#If starting fast, add a row to the db:
#fast_finished = False
#start_date_time using = current time
#end_date_time using = current time
if request.method == 'POST' and 'start_fast' in request.POST:
add_fast = logTimes(fast_finished=False,start_date_time=datetime.now(),end_date_time=datetime.now())
add_fast.save()
print(add_fast.start_date_time,add_fast.end_date_time)
print('Fast started')
#return render(request,'startandstoptimes/index.html')
return HttpResponseRedirect('startandstoptimes/index.html')
You can see my commented return line, this works but when I refresh the page I can resubmit the data, I want to avoid this. In researching my solution, I saw this could be solved using HttpResponseRedirect but I am not able to get this to work with my code, the more I change the more broken things become.
My application urls.py:
from turtle import home
from django.urls import path,include
from . import views
urlpatterns = [
path('', views.start_or_end_fast,name="start_or_end_fast")
]
My project urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('startandstoptimes.urls'))
]
I believe it is related to the URLs, due to the 404 message I see:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/startandstoptimes/index.html
Using the URLconf defined in myfastingsite.urls, Django tried these URL patterns, in this order:
admin/
[name='start_or_end_fast']
The current path, startandstoptimes/index.html, didn’t match any of these.
Am I going down the right route trying to use HttpResponseRedirect or is there a better solution?
class HttpResponseRedirect¶
The first argument to the constructor is required – the path to redirect to. This can be a fully qualified URL (e.g.
'https://www.yahoo.com/search/'), an absolute path with no domain
(e.g. '/search/'), or even a relative path (e.g. 'search/'). In that
last case, the client browser will reconstruct the full URL itself
according to the current path. See HttpResponse for other optional
constructor arguments. Note that this returns an HTTP status code 302.
See this link for more details: docs
As what the documentation says, HttpResponseRedirect accepts URL and not the path of your template. You should be doing it something like this:
from django.urls import reverse
return HttpResponseRedirect(reverse('start_or_end_fast'))

The "/" at the end of a url

I found an interesting thing I don't know how to solve:
urlpatterns = patterns('',
url(r'^$', 'my_app1.views.index', name='index'),
url(r'^path1/path2/', 'my_app1.api.method1')
// or url(r'^path1/path2', 'my_app1.api.method1')
)
I don't want the urls to contain "/" at the end.
If I go to http://localhost:8000/path1/path2 it redirects me to http://localhost:8000/path1/path2/ with the "/" at the end. Whatever I do to get rid of the "/" at the end of the url, I fail at. It seems there's no way to do so, unlike in Rails. Is it true?
You can control it using settings.APPEND_SLASH.
By default, it's True. Change the value to False in the project settings file.
APPEND_SLASH = False
But if you set it, accessing the page /path/path2 will result 404 error. You need to change the url pattern:
url(r'^path1/path2/?', 'my_app1.api.method1') # To match url with/without trailing /

Support old and new URI versions both working without breaking the reverse()

How can I support old and new URI versions both working without breaking the reverse()?
For example, I have:
urlpatterns = patterns('',
url(r'^(old_part|new_part)/other/$', 'some_view'),
)
In this case /old_part/other/ and /new_part/other/ point to the same view but reverse() method fails because it doesn't know how to form link properly.
Also, what if we have url(r'^(old_part|new_part)/other/', include(sub_patterns)) how can it be handled?
Do you have any ideas?
Thanks for your help.
I suppose you are migrating. This means you don't want old url work, you want it to redirect to new url. Probably with 301 HTTP code (permanent redirect).
Having several urls for same content makes your site harder to use and hurts your SEO. Permanent redirect will tell Google and any other search engine to reindex page with new address.
You can do it this way in Django:
from django.views.generic import RedirectView
urlpatterns = patterns('',
url(r'^new_part/other/$', 'some_view'),
url(r'^old_part/other/$',
RedirectView.as_view(url='new_part/other/', permanent=True)),
)
If you need to capture everything with a subpath, you can capture url ending and add it to redirect url this way:
urlpatterns = patterns('',
url(r'^new_part/other/$', include(sub_patterns)),
url(r'^old_part/other/(?P<rest>.*)$',
RedirectView.as_view(url='new_part/other/%(rest)s', permanent=True)),
)
You can use redirect_to generic view in Django 1.4 and earlier.
If you want without a redirect, you could try this
url(r'^(?P<url>old_part|new_part)/other/$', 'some_view', name='some_view'),
Then your view will look like this
def some_view(request, url):
...
Then call reverse like this:
# will return /old_part/other/
reverse('some_view', kwargs={'url': 'old_part'})
# will return /new_part/other/
reverse('some_view', kwargs={'url': 'new_part'})
Just redirect the old urls to the new ones (with a 301 Moved Permanently).
NB : if you really insist on supporting both sets of urls (not a good idea IMHO), you'll have to have two distinct url patterns, and choose which one reverse() should resolve to.

Django, how to pass just the last segment of url to view

I'm attempting to pass a string from the end of a url to a view function, but I'm getting the entire url passed to render_form() i.e. if I input "myurl.me/prepend/identifier" I get "prepend/identifier/" when I just want "identifier"
These are my urls.py files, the top one is located in an app directory, the bottom one is in the project dir:
urlpatterns = patterns('',
url(r'^(?P<identifier>.+)$', views.render_form),
)
--
urlpatterns = patterns('',
url(r'^prepend/', include('the_ones_above.urls')),
url(r'^admin/', include(admin.site.urls)),
)
I think it might have somehting to do with the split over 2 urlpatterns in 2 separate files, any ideas what im doing wrong?
Thanks!
edit: the view looks like: def render_form(request, identifier=None):
oh, and this is the latest django (from git)
2nd edit: removed the rather superfluous 1st url, behavior is still the same
I will suggest you to simply write you url like.
url(r'^(?P<identifier>[\w]+)/$', views.render_form),
[\w] will tell you that you can pass word character (A-Za-z0-9_).

Redirected url not picked from urls.py

I am very new to Python and Django.
I am using Django - 1.4.5. I am trying to get user input from form, redirect the url with the user input like
Httpresponseredirect('abc/xyz/%s' %variable)
I could see in browser that the response is redirected, but it throws a 404 error. The urls.py also has the url defined.
urls.py
urlpatterns = pattern('',
url (r'abc/xyz/(?P<variable>)/pqr' , 'view_name')
)
Can you please throw some light on it.
On further debugging I could figure out that the issue is with passing the argument to reverse function. When I pass a static page with no arguments, it redirects to the correct view. But when I redirect with arguments it throws me a NoreverseMatch error. I am redirecting it this way
return HttpResponseRedirect(reverse('view_name', kwargs= {'group':'group'}))
In urls.py it is defined as:
url (r'app/$' , 'app.view.app') ,
url (r'^my/first/(?P<group>)/$ , 'app.webapi.json.list_record', name ='view_name;),
list_record is a function in app.webapi.json.py.
Please let me know if any more details is required.
User reverse function in you view, first add a url name:
Httpresponseredirect(reverse('my_view_name', args=[variable]))
and (like #sushail said) fix the regexp:
urlpatterns = pattern('',
url (r'^abc/xyz/(?P<variable>)/pqr/$' , 'view_name', name='my_view_name')
)
you need to use complete path as the regexpression matchs abc/xyz/..../pqr
Httpresponseredirect('/abc/xyz/%s/pqr/' %variable)
and like (like #lalo said)
urlpatterns = pattern('',
url (r'^abc/xyz/(?P<variable>)/pqr/$' , 'view_name')
)
please checkwith / at begining and end, what is the view_name, it looks like you must have such a view in project directory,or you have to add the apppath in urlpatterns
`urlpatterns = pattern('<yourappname>.views',`

Categories