Django URL complicated patterns and paths - python

I'm trying to generated nested url paths. So far I could only generate 1 level urls. When I try second level urls it doesn't get called anymore, it still only shows the first level url although the address bar on the browser does direct to the second level url. Is this possible or do I need to create a new app?
urls.py
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView, TemplateView
from dashboard.models import IPARate,PCPRate
from dashboard import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^medicare/', ListView.as_view(queryset=IPARate.objects.all().order_by("id"), template_name='dashboard/medicare.html')),
url(r'^medicare/medicarepcp/$', ListView.as_view(queryset=PCPRate.objects.all().order_by("id"), template_name='dashboard/medicarepcp.html')),
url(r'^medicare/', views.medicaid, name='medicare'),
url(r'^medicare/medicarepcp/$', views.medicarepcp, name='medicarepcp'),
]

You need to add a dollar (end of line character) to the r'^medicare/ regex, so that it matches /medicare/ but not other URLs like medicare/medicarepcp/.
url(r'^medicare/$', ListView.as_view(queryset=IPARate.objects.all().order_by("id"), template_name='dashboard/medicare.html')),
url(r'^medicare/medicarepcp/$', ListView.as_view(queryset=PCPRate.objects.all().order_by("id"), template_name='dashboard/medicarepcp.html')),
The third and the fourth regexes are the same as the first and the second respectively. Django will always match the first two URL patterns, so you need to change the third and fourth URL patterns to something else.

The order of URLs is important, as Django will react to the first URL pattern that matches the request. A good habit is to put all of your "sub" URLs first, then the top level of that section last, so it works as a fall-back if no others match (i.e. put your '^medicare/$' last).

Related

Cant get URL,s in urls.py to work on DJANGO project

This is the urls.py file for the main site in my Django project.
Ive got a category table and a country table linked to a product table and I cant get all the urls in the code below working. If i put the category_detail url in the list just after the slug:category_slug>/slug:slug/', product_detail url those urls work and country_detail links dont. If i put the country_detail urls after the slug:category-slug>/slug:slug/', product_detail url then only the country_detail url works. Any help appreciated
from django.contrib import admin
from django.urls import path
from core.views import frontpage
from store.views import product_detail, category_detail,country_detail
urlpatterns = [
path('', frontpage, name='frontpage'),
path('admin/', admin.site.urls),
path('<slug:category_slug>/<slug:slug>/', product_detail, name='product_detail'),
path('<slug:slug>/', country_detail, name='country_detail'),
path('<slug:slug>/', category_detail, name='category_detail'),```
If i put the category_detail url in the list just after the slug:category_slug>/slug:slug/', product_detail url those urls work and country_detail links dont. If i put the country_detail urls after the slug:category-slug>/slug:slug/', product_detail url then only the country_detail url works.
This is because Django will use the first route that matches. Since the rules to match country detail and product detail are both exactly the same, whichever one is first is the one that will match.
To solve this, you need to rethink your API design and create routes that can be matched unambiguously.
Often we design a REST API around "resources" and "collections". This means we will have a route /products/ such as to interact with a collection and /products/1 to interact with a specific product resource.
For the collection route /products, we can add the ability to pass in query parameters to filter on a category or country with something like /products?country=United+States (note the + is the URL encoded version of a space). To allow this on the API side, you will need to get the query parameters from the request object and then add a filter to your queryset. I won't get into the details here, but you can find more information about this with some googling.
For the resource route products/1, we might want to get related objects, like the categories for that country. In such a case, we would create a route like products/1/categories. I will leave the details for implementing the view for this as an exercise for the reader.
Try this
urlpatterns = [
path('', frontpage, name='frontpage'),
path('admin/', admin.site.urls),
path('product-detail/<slug:category_slug>/<slug:slug>/', product_detail, name='product_detail'),
path('country-detail/<slug:slug>/', country_detail, name='country_detail'),
path('category-detail/<slug:slug>/', category_detail, name='category_detail'),
]

Overiding URL pattern from a third party app

I am using django-registration app and I am implementing the Remember me functionality snippet
Basically, the registration app, needs you to define one URL only,
url(r'^accounts/', include('registration.backends.default.urls')),
under the hood, it defines default urls like /accounts/login, /accounts/logout, each of which points to django.contrib.auth.views functions.
I need to overwrite the login() function, as well as the accompanying URL.
So how do I overwrite URL accounts/login in my urls.py, keeping all the rest urls as default?
Django will use the first URL pattern that matches. So in your urls.py, add a pattern for accounts/login before you include the urls from django-registration. All other URLs will be handled by django-registration.
You could try explicitly catching the accounts/login url request before it hits your more general accounts/* url catcher.
Maybe
# first catch your custom login
url(r'^accounts/login', include('my_custom_login.urls')),
# and everything else beginning with accounts/
url(r'^accounts/', include('registration.backends.default.urls')),

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_).

Including other URL patterns

I have what I think is a pretty simple URL configuration for a public API I'm building in django:
# public API, in urls.py
(r'^api/', include('api.urls'))
# in api/urls.py
api_key_patterns = patterns('api.geoprocessing',
url(r'^land-use/', 'landUse', name='geoprocessing_land_use'))
urlpatterns = patterns('',
url(r'^(?P<api_key>(.+))/', include(api_key_patterns)))
However, when I make a request to /api/123/land-use/ Django's URL resolver cannot find a match. When I debug the urls it has tried, it resolves the above to this:
^api/ (?P<api_key>(.+))/ land-use/ [name='geoprocessing_land_use']
Notice the spaces between (?P<api_key>(.+)) and land-use. Why are these spaces inserted for each include, and how can I get a match?
Update
If I hard-code a url for ^api/(?P<api_key>(.+))/land-use/ I am able to get a match.
Also, if I add a character after the trailing / the URL match also works:
api_key_patterns = patterns('api.geoprocessing', url(r'^and-use/$', 'landUse',name='geoprocessing_land_use'))
urlpatterns = patterns('', url(r'^(?P<api_key>(.+))/l', include(api_key_patterns)))
Try:
urlpatterns = patterns('api.geoprocessing',
url(r'^land-use/(?P<api_key>(.+))/$', 'landUse',
name='geoprocessing_land_use'))
)
I'm not sure what you're trying to accomplish by including a pattern when it doesn't seem like you need to be doing that.
Looks like using a (.+) group within my regular expression was forcing the django URL resolver to look for a character that wasn't there. This always parses when there are characters following the trailing slash, but when this group sits at the end of the url segment, a space is tagged at the end.
I resolved this by exchanging the (.+) group with a simple word matcher \w+:
(r'^api/(?P<api_key>\w+)/', include('api.api')),

any method to mix these urls in django

the usl :
(r'^account/', include('account.urls')),
(r'^account/', include('django_authopenid.urls')),
i want to use these url , and i dont want to mix it by my hand one by one , it is not very easy ,
has a method to do this in django .
thanks
Your own code can work properly in many cases, but if not you can do
this:
Create your own urls.py file:
from account.urls import urlpatterns as accounts_urlpatterns
from django_authopenid.urls import urlpatterns as authopenid_urlpatterns
urlpatterns = patterns("")
urlpatterns += accounts_urlpatterns
urlpatterns += authopenid_urlpatterns
What you do will work, with the caveat that any pattern that would match an entry in both would be found by the first one you list.
For instance, the url /account/openid/foo/ might match a pattern in django_authopenid.urls that is r'^openid/(.*)/$', but that would never hit if there was a match in account.urls that also matched, such as r'^(.*)/foo/$'.

Categories