Django Regex URL pattern overriding other URLs - django

I am working on a project which requires to display the data about a city which is requested through the url like example.com/city1 for city1 information etc.
I have used the below url pattern & view in my app. This view is working fine.
url(r'^(?P<cityId>[-\w]+)$',views.cityindex,name='cityindex'),
def cityindex(request, cityId):
city = City.objects.filter(url = cityId)
if len(city) == 0:
return redirect('/404')
return HttpResponse('City Data Extracted')
But when I try to open other urls like /admin or urls from other app it is being redirected to my cityindex view and then to 404 page as handled in my view above.
Below is the url patterns I used in my main urls.py file.
url(r'^', include('main.urls')),
url(r'^admin/', admin.site.urls),
url(r'^login_redirect/', include('loginapp.urls')),
I am presently using Django 1.11.12. Is there any way to stop this url from overriding?
Edit :
Urls in my main.urls file
url(r'^$',views.index,name='index'),
url(r'^about$', views.aboutpage,name="aboutpage"),
url(r'^terms$', views.termspage,name="termspage"),
url(r'^privacy$', views.privacypage,name="privacypage"),
url(r'^(?P<cityId>[-\w]+)$',views.cityindex,name='cityindex'),

To achieve this, think of sceanarios like this
1- www.example.com/cityname/
2- www.example.com/about/Us/
3- www.example.com/others/terms/
4- www.example.com/others/privacy/
Anytime you want to have other url like www.example.com/faculty/list
you use number 2-4 while you use the first to achieve your city name.
I have tested this to work in the following format
urlpatterns = [
url(r'^about/us/$', views.about_page), #about us or any other page
url(r'^(?P<cityname>\w+)/$', views.cityindex), #cityname
]
and in my view.py, i can catch the city name given like this
def cityindex(request, cityname):
data = cityname
#you can do anything you want here
return HttpResponse(data)
NB: the cityname could a number so you may decide to use it as city id instead, however, ensure it was converted to an integer in your view if you prefer to use cityid
I hope this helps

Related

Loop in a URL Django

I wanted to access different categories through the URL, is it possible to make a loop or something like that? Which iterates until the end of the URL, no matter how much categories are there.
For example my code without this loop is below, and is limited to 6 subcategories.
urls.py
path('<cat1>/<cat2>/<cat3>/<cat4>/<cat5>/<cat6>', views.AdList.as_view(), name='ad_list'),
I guess the easiest way to go would be to add multiple urls to your urlpatterns pointing to the same view.
For instance:
# urls.py
urlpatterns = [
...
]
# if you really want urls being abled to "receive" one to 6 categories in such a way:
for i in range(1, 6):
new_url = 'cars/'
for j in range (0, i):
new_url += f"<str:cat{j}>/"
urlpatterns.append(path(r'f{new_url}', your_view.as_view(), name="your_view")
This will work, because you can have multiple urls pointing to the same view. Then, you will have to check in your view whether or not such category is provided or not.

How can I use a catch all route using `path` or `re_path` so that Django passes all unmatched requests to my index view?

My url patterns look like this:
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')),
re_path('.*', IndexView.as_view()),
]
This works but it matches all URLs, including those prefixed with admin and api. I want those URLs to still match, and for any unmatched URLs to render IndexView.
Before 2.0 I used this regex for this purpose. I tried using it in re_path but that didn't work, which is what led me to trying the above.
url(r'^(?P<path>.*)/$', HtmlView.as_view())
Use case is a SPA where I handle 404s client side.
Many thanks in advance.
You can use two entries (one for '/', another one for anything else), but using path for both of them, which should be (slightly) more efficient:
urlpatterns = [
path('', IndexView.as_view(), {'resource': ''}),
path('<path:resource>', IndexView.as_view())
]
In this case, I'm using <path:resource> because path catches all resource names, inluding that with / in them. But it does not capture the main index resource, /. That's why the first entry. The dictionary as last argument for it is because we need to provide a resource parameter if we want to use the same view than in the second entry.
That view, of course, should have 'resource' as a paremeter:
def as_view(request, resource):
...
So as I said in the question description, trying the regex I was using before Django 2.0 in re_path did not work. It would basically match for all requests except / (i.e., index path). I fixed this by using both that regex and a second path matching / specifically. Here's the code:
urlpatterns = [
re_path(r'^(?P<path>.*)/$', IndexView.as_view()),
path('', IndexView.as_view()),
]
With these changes my other routes would match and these two routes would account for all other urls.
One Idea to go about this is let the django catch 404.
url.py
from django.conf.urls import handler404
handler404 = 'app_name.views.bad_request'
and in your views.py
views.py
def bad_request(request):
return redirect(reverse('home'))
You can always do some regex thingy to catch unmatched urls. but hey this gets the job done. :)

How to go to a different page from current in Django template

urlpatterns = [
url(r'^$', predict_views.index, name = 'HomePage'),
url(r'^admin/', admin.site.urls),
url(r'^Update_db/$', predict_views.Update_db, name = 'Update_db'),
url(r'^compare/(?P<phone1_id>[0-9]+)/(?P<phone2_id>[0-9]+)/$',predict_views.Compare, name = 'Compare'),
url(r'^predict/(?P<phone_id>[0-9]+)/$',predict_views.Predict, name = 'Predict'),
]
these are my url patterns in djano. I want to go to compare directly from predict which is not possible for me currently because :
when I go to predict the url is 127.0.0.1:8000/predict/1 now when i go to compare from predict the url becomes 127.0.0.1:8000/predict/1/compare/1/2 which is not the expected url .. my url should be 127.0.0.1:8000/compare/1/2
I have seen django docs there are some redirect methods but I do not understand them.
Any help is appreciated.
Something tells me you are accidentally using relative urls. In your template, try the following:
Compare Page

Django url patterns for different currencies

I am building a site in english and simply want to offer a small subset of currencies. For SEO and caching I am planning to develop the following url structure with the prices being displayed in the relevant currencies.
Home(s)
site.com/
site.com/au/
site.com/us/
...
Categories Index Pages
site.com/categories/
site.com/au/categories/
site.com/us/categories/
...
Product Index Pages
site.com/categories/category1/
site.com/au/categories/category1/
site.com/us/categories/category1/
...
Product Pages
site.com/categories/category1/product-1/
site.com/au/categories/category1/product-1/
site.com/us/categories/category1/product-1/
...
This is my attempted url.py
urlpatterns = patterns('',
#url(r'^$', views.homeCurrency, {'cur_slug': '' }, name='home'),
url(r'^(?P<cur_slug>[:au|nz|us|eu|ca|uk]+)/$', views.homeCurrency, name='home'),
url(r'^categories/', include('parts.urls', namespace="parts")),
url(r'^(?P<cur_slug>[:au|nz|us|eu|ca|uk]+)/bike-parts/', include('parts.urls', namespace="parts")),
)
This is the sort of dynamic url I need in my base.html
Home
My problem is two fold (I think)
Firstly, I can't allow for the default case i.e. site.com(/) in the url pattern so that there is a common url name that can be used dynamically throughout each version of the site.
Secondly, even ignoring the default case, I am getting the following error:
Request Method: GET
Request URL: site.com/au/
Django Version: 1.5.4
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'home' with arguments '()' and keyword arguments '{}' not found.
Any help would be greatly appreciated as this is my first project in Django. Cheers
The first problem is with your regex. [] means character class, i.e. [a|bc] would match a, |, b or c but never bc.
Hence, your regex should be using groups ():
url(r'^(?P<cur_slug>au|nz|us|eu|ca|uk)/$', views.homeCurrency, name='home'),
If you're not 100% confident with regex, you should have a look into the excellent surlex library, which provides a neat little DSL for writing URL patterns.
from surlex.dj import surl
// a macro for valid currencies
surlex.register_macro('$', r'au|nz|us|eu|ca|uk')
urlpatterns = patterns('',
// macros are only used in match groups (surrounded with `<>`)
surl(r'<cur_slug:$>/$', views.homeCurrency, name='home'),
surl(r'<cur_slug:$>/bike-parts/$', include('parts.urls', namespace="parts")),
)
regarding your choice of "dynamic url", why not instead base your url roots on locale, and choose the correct currency based on locale. REF

Django url regexp not working

I'm trying to get my head around regexp in Django urls. I'm currently developing locally and I want to be able to direct a request such as http://localhost:8000/options/items/item-string-1121/ to the 'details' view in my app called 'options', passing in the final number part of the request string (1121) as a parameter 'id' to the view function.
The signature for details in options/views.py is as follows, taking id=1 as default:
def details(request, id=1):
...
I have the following in my root urls.py:
...
urlpatterns += patterns('',
url(r'^options/, include(options.urls')),
)
and in options/urls.py:
urlpatterns = patterns('options.views',
url(r'^items/(.+)(P<id>\d+)/$', 'details'),
...
)
Now when I try to request the above URL the dev server says it tried to match against the pattern ^options/ ^items/(.+)(P<id>\d+)/$ but it doesn't match.
Can anyone see the problem?
You need a non-greedy quantifier on the (.+), so r'^items/(.+?)(P\d+)/$'. Otherwise that first glob happily eats until the end of the string, preventing the ID from ever matching.
You are missing quotes.
urlpatterns += patterns('',
url(r'^options/, include(options.urls')),
)
Should be
urlpatterns += patterns('',
url(r'^options/', include('options.urls')),
)
I'm not too sure of your expression, might try this:
urlpatterns = patterns('options.views',
url(r'^items/(?<=-)(?P<id>\d+)/$', 'details'),
...
)