creating catch-all url() entry using regex - python

So had zero issues with my Django and React URL routing in dev, but now that I am trying to move to production, running into all kinds of issues.
Yes, I suck when it come to regex. It looks like a cat walked on a keyboard. Definitely something I need to sit down and commit to learning.
In dev, my catch-all was just the following which worked perfectly:
url(r'', TemplateView.as_view(template_name='index.html')),
In production, I got Uncaught SyntaxError: Unexpected token <. This, as it was explained to me, had to do with JS being caught in the url instead of index.html and that the JS needed to "pass through". I was told to try:
url(r'^$', TemplateView.as_view(template_name='index.html')),
This worked. The web application loaded and I was able to navigate.
Another problem came up, however, when it came to verification emails links. I am running into issues with Page not found (404) which, again, wasn't an issue in my dev setup.
The email links look like the following:
https://test.example.com/auth/security_questions/f=ru&i=101083&k=6d7cd2e9903232a5ac28c956b5eded86c8cb047254a325de1a5777b9cca6e537
What I get back is this:
Page not found (404)
Requested URL: http://test.example.com/auth/security_questions/f%3Dru&i%3D101083&k%3D6d7cd2e9903232a5ac28c956b5eded86c8cb047254a325de1a5777b9cca6e537/
My react routes are the following:
<App>
<Switch>
<Route exact path='/auth/security_questions/f=:f&i=:id&k=:key' component={SecurityQuestions} />
<Route exact path='/auth/*' component={Auth} />
<Route exact path='/' component={Auth} />
</Switch>
</App>
This should render /auth/security_questions/... route.
My urls.py is the following:
urlpatterns = [
# API authentication entry point
url(r'^api/auth/', include('authentication.urls', namespace='signin')),
# Any requets that come through serve the index.html
# url(r'^$', TemplateView.as_view(template_name='index.html')),
] + static(settings.STATIC_URL,
document_root=settings.STATIC_ROOT)
Also, the authentication.urls:
urlpatterns = [
url(r'^security_questions/', SecurityQuestionsAPIView.as_view(), name='security_questions'),
]
It seems like Django is trying to handle the routing, there obviously isn't a route that matches, when really it should just render index.html and let react-router-dom take over to send requests to the API from the FE. Thus, it seems I need to make a catch-all that lets JS through.
I came across this question which seemed relevant: react routing and django url conflict. So I added the following so that I have a / catch and then "everything-else" catch-all.
# match the root
url(r'^$', TemplateView.as_view(template_name='index.html')),
# match all other pages
url(r'^(?:.*)/?$', TemplateView.as_view(template_name='index.html')),
Still won't render the verification links. Tried a few other variations for the last-catch all URL:
Django route all non-catched urls to included urls.py
url(r'^', TemplateView.as_view(template_name='index.html')),
Results in Uncaught SyntaxError: Unexpected token <
django catching any url?
url(r'^.*', TemplateView.as_view(template_name='index.html')),
See the preceding.
So going to dig into Django, regex, and try to sort this out, but in the mean time...
What am I doing wrong here?

Ok, was almost there. I modified:
url(r'^(?:.*)/?$', TemplateView.as_view(template_name='index.html')),
To this:
url(r'^(?:.*)/$', TemplateView.as_view(template_name='index.html')),
Which prevented the Uncaught SyntaxError: Unexpected token < error. It would load parts of the web application, but not in its entirety. That issue was due to URL-encoding so I had to clean up the formats of my URLs. Question I had about it here:
Prevent URL encoding that is removing equals signs from URL
Now everything seems to be loading correctly.

Related

Django Admin Page not found when including MEDIA_ROOT setting

this is my first question so please point me to the right direction in case I miss something of importance ☺️
So my problem is the following:
I'm currently creating a website with Django, which is supposed to list a variety of projects from the database. Each project has a picture associated with it. The path to this picture is saved in the database (each picture is added as models.ImageField() to the projects model). In order to serve them, I added MEDIA_ROOT = os.path.join(BASE_DIR, 'main/media') to my settings.py and added the following snippet to my urlpatternsin urls.py: + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Now to the crux of it: Everything works fine, except I can't open my admin panel now. The media files are served as expected in the projects overview, but at soon as I try to open the /admin page, I get following error message:
Page not found (404)
“/Users/.../main/media/admin” does not exist
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Raised by: django.views.static.serve
as soon as I remove + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) from my url patterns, the admin page works fine again, however the media files are not served anymore.
Can someone show me what I've broken here?
Thank you very much!
I had the same problem. I had a link on my site, that when pressed took me to admin panel.
The mistake was that I was missing a trailing slash.
This did not work:
Admin
This worked:
Admin
You might not have added the MEDIA_URL path in setting.py.
In your case:- add this to settings.py:- MEDIA_URL = "/main/media/". If it doesn't work, try removing one of the two corner slashes. Hope it will work.

LocaleMiddleware redirects on a non-i18n url pattern

I'm using Django's LocaleMiddleware to internationalize a part of the website I'm working on.
Here is my project's urls.py:
from django.conf.urls import patterns, include, url
from django.conf.urls.i18n import i18n_patterns
urlpatterns = patterns('',
url(r'^api/stuff/(?P<stuff_id>)\d+/$', ApiStuff.as_view()),
)
urlpatterns += i18n_patterns('',
url(r'^stuff/', DoStuff.as_view()),
)
The problem is, when ApiStuff.as_view() returns a 404 response (other error codes behave as expected), the LocaleMiddleware operates the request to make it redirect to /en/api/stuff/<stuff_id>, even though the /api namespace is clearly not in the i18n_patterns (at the end, it generates a 404 error too, but the content of my original response is lost).
Here is the code of ApiStuff:
import django.http
from django.views.generic import View
from project.stuff.models import Stuff
class ApiStuff(View):
#staticmethod
def get(request, *args, **kwargs):
stuff_id = kwargs['stuff_id']
try:
stuff = Stuff.objects.get(pk=stuff_id)
except Stuff.DoesNotExist:
return response({"error": "stuff not found"}, 404)
result = stuff.serialize()
return response(result)
def response(data, status=200):
data = json.dumps(data)
return django.http.HttpResponse(data, status=status, content_type='application/json')
I'm using django 1.6.10 (I know, it's late, but I can't update the version right now).
Am I missing something?
This is an old bug that has been tracked here:
https://code.djangoproject.com/ticket/17734
The 404 error handler is a default handler of Django. It obviously takes the current language into account in order to translate the "not found" message.
Unless you can upgrade to a newer version you probably need to define your own error handler (including route/url).
EDIT:
As a workaround it might be possible to extend the LocaleMiddleware and maybe also CommonMiddleware. However, it could be that the 404 handler does its magic nevertheless. Might be worth a shot though because it should only require few lines of code.
Citing the ticket:
when you request /api/raising/404/, it is redirecting the user to /en/api/raising/404/ (assuming it detects the language as en). If it tests before redirecting the user if /en/api/raising/404/ is resolvable, it would find out that this would raise a 404 as well and thus would not redirect the user.
EDIT 2:
As an alternative you could simply not use i18n_patterns and just detect/switch the language via browser/cookie/parameter. I did that for a project (which included Django CMS) where I kept running into problems with these URLs. It is definitely not a prerequisite for localized Django sites to use i18n URL patterns. It's just something on top, but not at all necessary. Localization will work just fine without it. If you need help with the middleware for switching languages, drop a comment.
One can get around this issue by using following url config
urlpatterns += i18n_patterns(
url(r'^(?!api.*)stuff', DoStuff.as_view()),
)

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.

404 Not Found Django when clearly in urls.py

I have the following code in the urls.py file
urlpatterns = patterns('ecomstore.accounts.views',
(r'^register/$', 'register', {'template_name':'registration/register.html', 'SSL':settings.ENABLE_SSL}, 'register'),
(r'^my_account/$','my_account', {'template_name':'registration/my_account.html'},'my_account'),
(r'^order_details/(?P<order_id>[-\w]+)/$', 'order_details', {'template_name':'registration/order_details.html'}, 'order_details'),
(r'^order_info//$', 'order_info', {'template_name':'registration/order_info.html'},'order_info'),
)
All the redirects work i.e. /register/, /my_account/, etc except for /order_info//. I'm getting a 404 page not found error and I'm not sure why this is any different than the others.
It's working on my development server, but not apache for some reason if that has anything to do with it.

decoupling the URLConfs(Python/Django): current URL does not match any URL pattern after ERROR

I have just started teaching myself python/django and have been following the django tutorials. I have got stuck at the decoupling of URLConfs. I have copied the code to respective files from the tutorial but I am getting this error:
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
^polls/ ^/$
^polls/ ^/(?P<poll_id>\d+)/$
^polls/ ^/(?P<poll_id>\d+)/results/$
^polls/ ^/(?P<poll_id>\d+)/vote/$
^admin/
The current URL, polls/, didn't match any of these.
I have got urls.py in both mysite and polls folder as asked by the tutorial (https://docs.djangoproject.com/en/dev/intro/tutorial03/)
Short answer: remove the first / in the URL configs on polls.urls.
Long explanation:
The problem here, as Julian mentioned in the comments is that you have an extra slash in the URL configs.
When you have the following in your root URL config:
url(r'^polls/', include('polls.urls')),
This essentially 'chops off' the polls/ part of the URL string and passes the rest on to polls.urls. So if you try and get the URL polls/13/results, the polls/ will be handled by my site.urls and the rest will be given to polls.urls.
Your polls.urls file seems to be requiring a preceding / on the string however, and because this has been removed already it doesn't exist. The caret ^ character means the beginning of the string so all of your configs at the moment require that they start with a / at the point that polls.urls receives them, they shouldn't do this otherwise you are expecting the following:
/polls//13/results
instead of:
/polls/13/results
I hope this answers everything!

Categories