Django URL match in HttpResponse object? - django

In django, when a URL is matched, the match group is passed as a second parameter to the view function, the first being a HttpRequest object. For example, with a URL patter like this
'/foo/(\d{2})/', 'app.views.handler'
the handler routine will have
def handler(request, value):
where value will contain a two digit number (as a string).
My question is: is value also contained in the request object, and if yes, how can I get it (of course, parsing the URL from the request object is not an option, too impractical).
Thanks

I'm not going to debate the merit of your idea. Just try to answer your question:
No there is no way, other than applying the regex to the URL again, to get at the url parameter.
Your view will be the first point where the parameter list will be available. Why don't you just create a wrapper object to encapsulate your request and your parameter list at that point?
Just pass that around...

Can you give any reason why you would need this?
I don't see why parsing the url path is 'impractical', given that you've already got a regexp that works, in your urlconf.

Related

What is best practice for passing variables via GET?

I am passing a variable in my URL:
mydomain.com/app/?next_page=my_page
I can get this variable in a view with:
def mypage(request):
var = request.GET['next_page']
Is it best practice to also change the URL to require next_page? Something along the lines of:
path('app/?nextpage=<str>', mypage, name='my_page')
What's best practice? If so, what's the correct syntax for this (I know the example is incorrect)?
It depends on your needs.
Do not define a fixed url route; if you use the query parameters for filtering and there is more than one possible parameter
Example: "app/photos?size=100x100" and "app/photos/?color=blue"
Define a fixed url route; if it will be the same for each and every page, like details of a particular page:
Example: "app/orders/123123123" and "app/orders/123123123"
Btw, the correct syntax is:
path(app/<str:next_page>/, mypage, name="my_page")
You should take a look at path patterns. Enforcing a GET parameter in a path is not really a good practice. So if you want to require a username for example you can use:
path('bio/<username>/', views.bio, name='bio'),
You can find more patterns in Django documentation to catch strings, slugs, integers etc.
And in views you should define your function as such:
def mypage(request, username):
...code...
About GET:
Keep in mind that request.GET["value"] will raise a ValueError if that parameter does not exist. So you can catch that error to inform user that they are missing a parameter. (This will make this parameter obligatory.)
You can also use request.GET.get("value") which will return None if the key does not exist. If you want to use a default parameter you can use of course, request.GET.get("value", "default")
You can use as many parameters as you want in your link with or without path patterns. Their values will be stored in request.GET

How to use variable at start of django url to return to view?

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'),

Force django querystring in url

Say you have a url like this:
/cats/?filter=kittens
Is it possible to build a django url pattern that forces the use of the querystring?
Currently I have:
url(r'^/cats/$', views.CatsListView.as_view(), name='cats')
Now I want to add the querystring and get a different view, something like this:
url(r'^/cats/?filter=(?P<filter>.+?)$', views.CatsFilteredListView.as_view(), name='cats-filtered')
Is it possible to do something like this and still keep the querystring in the GET parameter of the request?
Remember that this is just a testcase, I, and you should too, know that filtering like probably this isn't the way to go..
Short answer: no, it's not possible. Django url patterns match only on the "path" componant of the url, period.
No, it's not possible to do this. If you really need two separate views, you can write a view that dispatches the correct view.
def cat_list_view(request, *args, **kwargs):
if 'filter' in request.GET:
return cat_list_filter_view(request, *args, **kwargs)
else:
return cat_list_unfiltered_view(request, *args, **kwargs)
However, for your example of CatsListView and CatsFilteredListView there is probably a better way to combine the views. For example you might be able to do the filtering in the get_queryset method.
While it is true that you cannot manipulate the path component like that, you can pass a dictionary in. It's a 3rd unnamed argument.
This approach can be useful if you want to use the same view for multiple resources, and pass data to configure its behaviour in each case (below we supply a different template in each case).
path('url/', views.my_reused_view, {'my_template_name': 'some_path'}, name='aurl'),
path('anotherurl/', views.my_reused_view, {'my_template_name': 'another_path'}, name='anotherurl'),
Note: Both extra options and named captured patterns are passed to the view as named arguments. If you use the same name for both a captured pattern and an extra option then only the captured pattern value will be sent to the view (the value specified in the additional option will be dropped).
Courtesy of https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views

Url paramter with a value with two words

I have a problem calling an url, i want to know whats the way to pass a value with 2 words like an argument or if my question is not possible
i have this in my url.py:
url(r'^tiendas/([\w-]+)/$', MostrarTiendas.as_view(), name='mostrartiendas'),
i want to pass a value called name_tienda but this field sometimes have 2 word and django return this error:
Page not found (404)
Request Method: GET
http://localhost:8000/tiendas/Tienda%20Amiga
thank for all
Change your url regex to this:
url(r'^tiendas/(?P<name_tienda>[-\w]+))', MostrarTiendas.as_view(), name='mostrartiendas'),

In Django, how do I deal with an "or" in the url regex once I get to the view?

I'm just learning Django, and am getting stuck with some url logic. I'm trying to allow either a category name or id in the url:
...
url(r'^(?P<booze_q>\w+|\d+)/$','glasses.views.booze'),
...
And then in thew view, only deal with that result once. However, if the url is a string - in this case, Whiskey, I get an error for trying to pass a string where an int is expected. This is the closest I've gotten so far:
def booze(request, booze_q):
booze = get_object_or_404(Booze,Q(pk=booze_q)|Q(name=booze_q))
return render_to_response('booze/detail.html', {'booze': booze})
But this returns an error: invalid literal for int() with base 10: 'Whiskey'
I'm sure it's a pretty easy thing, but this is my first Django app, so any help would be appreciated.
tl;dr: End result, I'd like mysite.com/1/ or mysite.com/Whiskey/ to both call the glasses.views.booze view, and get the object with id=1 or name=Whiskey
This is a common scenario you'll encounter quite often, which is typically handled by resorting to multiple arguments and having views behave differently based on which of the view arguments are then present or not.
What you do is first define a URL pattern that uniquely matches each specific case and then let Django's URL resolver set the arguments accordingly based on which of the patterns was matched.
Here's an example with a class based view, that performs two different queries based on which of the two keyword arguments, booze_id or booze_name, is set:
url(r'^(?P<booze_id>\d+)/$', BoozeDetailView.as_view()),
url(r'^(?P<booze_name>\w+)/$', BoozeDetailView.as_view()),
class BoozeDetailView(DetailView):
model = Booze
def get_object(self):
booze_id = self.kwargs.get('booze_id', None)
booze_name = self.kwargs.get('booze_name', None)
if booze_id:
return self.model.objects.get(id=booze_id)
else:
return self.model.objects.get(name=booze_name)
You will always get a string, even if the string contains a number.
1) You should not have a parameter that could be either an id or something else. One day you will enter an item whose name is a number and your app will fail.
2) When querying for pk with a string django automatically tries to convert it into an integer. You'll have to handle the non-pk case before constructing that query.