I need to bolt a quick city-specific thing onto a site I am currently building. I am going to do it something like this - http://example.com/XX/normal-slug. What I have set up in my urls.py is this:
url(r'^(?P<city>[a-zA-Z]{2})/', include('homepage.urls', namespace='homepage')),
url(r'^(?P<city>[a-zA-Z]{2})/section/', include('section.urls', namespace='section')),
# etc
The problem I am encountering now is that all of a sudden my methods all are now expecting a "city=XX" param. I plan to process the actual city business logic in a middleware. My question is... is there anyway have django "ignore" the named param? I don't want to modify all my views now to take either **kwards or 'city' param. If I hard code the city code, it does what I expect:
url(r'^XX/section/', include('section.urls', namespace='section')),
So can I replicate that behaviour, but dynamically?
(Also, I plan on something more robust further down the line, probably Django Sites)
You can use a non-capturing regex to accept the parameter but not pass it to the views.
r'^[a-zA-Z]{2}/section'
Set the param as optional in the regexp with ?:
url(r'^((?P<city>[a-zA-Z]{2})/)?section/', include('section.urls', namespace='section')),
If city is not sent in the URL, your view will receive city=None
Related
I am trying to pass the first part of a django url to a view, so I can filter my results by the term in the url.
Looking at the documentation, it seems quite straightforward.
However, I have the following urls.py
url('<colcat>/collection/(?P<name>[\w\-]+)$', views.collection_detail, name='collection_detail'),
url('<colcat>/', views.collection_view, name='collection_view'),
In this case, I want to be able to go to /living and have living be passed to my view so that I can use it to filter by.
When trying this however, no matter what url I put it isn't being matched, and I get an error saying the address I put in could not be matched to any urls.
What am I missing?
<colcat> is not a valid regex. You need to use the same format as you have for name.
url('(?P<colcat>[\w\-]+)/collection/(?P<name>[\w\-]+)$', views.collection_detail, name='collection_detail'),
url('(?P<colcat>[\w\-]+)/$', views.collection_view, name='collection_view'),
Alternatively, use the new path form which will be much simpler:
path('<str:colcat>/collection/<str:name>', views.collection_detail, name='collection_detail'),
path('<str:colcat>/', views.collection_view, name='collection_view'),
I am using web2py and builing a REST api and have one of my URLs set up like this:
routes_in (
('/myapp/something/{?P<id>.*)/myfunction', /myapp/default/myfunction/\g<id>')
)
routes_out = (
('/myapp/default/myfunction/\g<id>', '/myapp/something/{?P<id>.*)/myfunction')
)
If my app is setup this way my function is not even entered into and I get an invalid request if I remove the id argument from the url that my url is being mapped to i.e. remove g<id> from above, I enter my function but the argument is not being captured.
I cannot change the structure of the URL as per my requirements and I am not sure how to go about this.
I would appreciate any pointers.
Thanks,
nav
The above does work in web2py I found that some other area of my code was breaking.
I'd like to send any route that doesn't match an admin route, to my "event" controller. This seems to be a fairly common requirement and a cursory search throws up all sorts of similar questions.
The solution, as I understand, seems to be using a negative lookahead in the regex. So my attempt looks like this:
$route['(?!admin).*'] = "event";
..which works. Well, sort of. It does send any non-admin request to my "event" controller, but I need it to pass the actual string that was matched: so /my-new-event/ is routed to /event/my-new-event/
I tried:
$route['(?!admin).*'] = "event/$0";
$route['(?!admin).*'] = "event/$1";
$route['(?!admin)(.*)'] = "event/$0";
$route['(?!admin)(.*)'] = "event/$1";
... and a few other increasingly random and desperate permutations. All result in a 404 page.
What's the correct syntax for passing the matched string to the controller?
Thanks :)
I don't think you can do "negative routing".
But as routes do have an order : "routes will run in the order they are defined. Higher routes will always take precedence over lower ones." I would do my admin one first then anything else.
If I suppose your admin path is looking like "/admin/..." I would suggest :
$route['admin/(:any)'] = "admincontroller/$1";
$route['(:any)'] = "event/$1";
I would like my urls to be case insensitive. Adding (?i) to the beginning of the regexp in urls.py does not work completely when using generic views.
Here is the url that I'd like to focus on:
url(r'^(?i)(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-A-Za-z0-9_]+)/$', BlogDateDetailView.as_view(model=Entry,
queryset=Entry.objects.all(),
date_field='pub_date',
slug_field='slug',
)),
The following work:
http://mysite.com/2012/jan/24/my-article
http://mysite.com/2012/JAN/24/my-article
The following does not work (i.e I get a 404):
http://mysite.com/2012/jan/24/My-Article
I think the reason it does not work is because the lookup query for the slug is case sensitive. In order to make this work, I believe I need to subclass (not sure if this is the right term) class SingleObjectMixin(object): since this is where queryset = queryset.filter(**{slug_field: slug}) happens. Perhaps I should subclass get_queryset().
I'd appreciate some guidance on how I could do this cleanly in django 1.3
Case-insensitivity in URLs is generally a bad thing. A resource should only really have one URL.
However, you can just use:
slug_field='slug__iexact'
But, I would instead catch the DoesNotExist exception, lower() the slug from the URL, try the query again with the new slug and return a redirect to the correct URL. You could actually check for uppercase letters before running the first query to avoid running unnecessary ones.
It's up to you :)
I'm designing a gallery application for viewing vehicle pictures and there are two parameters:
Manufacturer
Vehicle type
Right now you can view either, but not both. Urls go like so:
/manufacturer/#
/type/#
Where # is an ID number. How/can I format my URLs so it can accept both? My current solution is to do: /both/#/# but this requires some retooling since the application doesn't know when you want to filter by both. Any insight would be appreciated.
If you're in a situation where both are optional, perhaps your best bet is to handle it through GET parameters.
Probably that scheme will work for you:
views.py:
def filtered_view (request, manufacturer_id=None, type_id=None):
...
urls.py:
...
url(r'^manufacturer/(?P<manufacturer_id>[0-9]+)/((?P<type_id>[0-9])/)?$', filtered_view),
url(r'^type/(?P<type_id>[0-9]+)/((?P<manufacturer_id>[0-9])/)?$', filtered_view),
...
And depending on user’s way through the site, urls will be /manufacturer/123/, /manufacturer/123/456/ or /type/456/, /type/456/123/ (where 123 is a manufacturer id, and 456 is vehicle type id.)