I have a question about Django and it's routing system. I believe that it can be powerfull, but right now I am struggling with one issue I don't experience when working in other frameworks and I can't seem to get a grip on it. Worth to mention that I don't have much experience with Django at this point.
The issue is simple - I have a view which takes two optional parameters, defined like this
def test_view(id=None, grid=None):
Both parameters are optional and frequently are not passed. Id can only be an integer and grid will never be an integer (it is a special string to control datagrid when I don't want to use sessions). I have a route defined like this:
url(a(r'^test_view (\/(?P<id>\d+))? (\/(?P<grid>[^\/]+))? \/?$'), views.test_view, name='test_view'),
This works great and I am not having trouble with using one-way routes. But when I try to use the reverse function or url template tag, following error occurs:
Reverse for 'test_view' with arguments '('20~id~desc~1',)' and keyword arguments '{}' not found.
In this example I tried to find reverse without the id, just with the grid parameter. I have tried various methods of passing parameters to the reverse function:
(grid, )
(None, grid)
('', grid)
{id=None, grid=grid}
All of them result in same error or similliar one.
Is there a way to implement this in django? Maybe just disable the cool URL for the grid parameter. That is how I do it in for example Nette framework for PHP, isntead of having an url like this: 'localhost/test_view/1/20~id~desc~1' I have url like this: 'localhost/test_view/1?grid=20~id~desc~1'. This would be completely sufficient, but I have no idea how to achive this in Django.
As you note in your question, the best way to achieve this is to use standard GET query parameters, rather than doing it in the path itself. In Django you do that exclusively in the view; the URL itself is then just
url(r'^test_view$', views.test_view, name='test_view'),
and you request it via localhost/test_view?id=1&grid=20~id~desc~1. You get the params from request.GET, which is a dictionary-like object; you can use .get so that it does not raise a KeyError when the key is not provided.
def test_view(request):
id = request.GET.get('id')
grid = request.GET.get('grid')
Related
I am trying to make some tests in which asks for ads of a particular type
for instance:
http://127.0.0.1:8000/ads/?type=normal should return the normal ads
and
http://127.0.0.1:8000/ads/?type=premium should return the premium ads
the tests ask for the ads like this response = self.client.get(reverse("ads")) self.client is for the site.
Reverse() was the function i have been using for the other tests so i thought it would work as fine.
i was looking for a way i could send the parameters but there is nothing on the internet as far as i'm concerned and i have been struggling with this for hours.
┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻
If you need any more info i could bring you
i tried using:
reverse("ads", kwargs={"type": "normal"})
reverse("ads", QUERY_PARAMS={"type": "normal"})
reverse("ads", QUERY_KWARGS={"type": "normal"})
reverse("ads", {"type": "normal"})
These are all things I found online.
However, nothing worked.
When a URL is like domain/search/?q=haha, you would use request.GET.get('q', '').
q is the parameter you want, and '' is the default value if q isn't found.
However, if you are instead just configuring your URLconf**, then your captures from the regex are passed to the function as arguments (or named arguments).
Such as:
(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),
Then in your views.py you would have
def profile_page(request, username):
# Rest of the method
I am trying to create a parameter that is required using the Python Dialogflow API v2. My current code is as follows:
parts.append(Intent.TrainingPhrase.Part(text=value,
alias=value,
entity_type='#' + value))
This works to create the parameter, but it is not required. The obvious first attempt was to add a required=True param, but that was not expected by the function call.
Looking at their docs (https://googleapis.dev/python/dialogflow/latest/gapic/v2/types.html) there does not seem to be any required/mandatory field.
I started to dig a little into their code, and found similar - there does not seem to be a required or mandatory field, except when creating the parameter?
https://github.com/googleapis/dialogflow-python-client-v2/blob/7bf592684b4d5df0cd1f66dd414efe2350d0461e/dialogflow_v2/proto/intent.proto
Ah, got it. My mistake was that you can create parameters for an intent as I was doing above, and it will add the parameter, but not required. You can explicitly specify a parameter as well, which is what has the mandatory field. Like this:
if len(parameters) > 0:
for parameter in parameters:
intent_parameter = Intent.Parameter(
display_name=parameter.name,
value=parameter.name,
entity_type_display_name='#' + parameter.name,
mandatory=True
)
intent.parameters.extend([intent_parameter])
I would like to use the reverse url lookup available in a django template using keyword arguments instead of positional ones.
I have it working using positional arguments just fine as such:
HTML:
download
URL:
(r'^generator/download/(?P<customer_id>\d+)/$', 'generator.views.send_file', name='download'),
View definition:
def send_file(request, customer_id):
The problem is that I am noticing a security flaw in that now anyone can simply enter as a url like:
/generate/download/<any number>/
and download a file that is meant only for someone else. I understand that this risk might be able to be mitigated by using user permissions etc, but I still would like to add another layer of security just in case. Maybe I am wrong in my thinking that a keyword argument is safer in this regard because it is not simply available to be passed in the url... But that is what I am thinking.
The code as I think it should work looks like:
HTML:
download
URL:
(r'^generator/download/$', 'generator.views.send_file', name='download'),
View definition:
def send_file(request, customer_id=None):
customer = get_object_or_404(Customer, pk=customer_id)
... other code
meaning if /generate/download/ is entered in the url (without the accompanying kwarg) it would just give them 404.
but I am getting the following error when I try to use this code:
Reverse for 'download' with arguments '()' and keyword arguments '{u'customer_id': 33}' not found. 1 pattern(s) tried: ['generator/download/$']
I'm sure it is something silly that I simply passed over in the django url dispatcher docs, or perhaps it is in the way I am defining my view (perhaps I need **kwargs as the argument?) but I can't seem to find it for the life of me.
Your help is much appreciated.
Your assumption is unfortunately completely wrong. Keyword arguments are passed in the URL, they are simply sent to the view function in a different way - in kwargs instead of args.
The simplest way to solve your problem is just to check the user in the download function itself.
def download(request, pk):
obj = Download.objects.get(pk)
if obj.customer_id != request.user.id:
return HttpResponseForbidden()
I have such a problem: I want one method of the class to handle different URIs (for URI "/solution/add" and "solution/edit"). So I wrote such routing:
app = webapp2.WSGIApplication([webapp2.Route(r'/solutions/(add|edit)', handler='solution.SolutionPage:add_edit_solution'), ], debug=True)
And webapp2 gives 404 error. Could you please suggest the solution of this problem?
Ofcourse I can write different routes for every URI, but it's not so interesting.)
As the webapp2 docs indicate, you have to put the regex in angle brackets, with a colon separating name and expression. The name is optional, but
everything outside of <> is not interpreted as a regular expression to be matched
So something like this: '/blog/<:\d{4}>/<:\d{2}>' Or in your case, this:
webapp2.Route(r'/solutions/<:(add|edit)>',
handler='solution.SolutionPage:add_edit_solution')
If I can add something.
For my own purpose, I've try to create a handler which perform a little bit similar operation, but the point is that I've used self.request.host or self.request.route instead of arguments.
Doing this, and parsing the result with a switch case or if/elif/else loop, allow me to create a class named URIHandler which is use to route any kind of request to the correct ressources (even 404/500/yyy error pages) dynamicly whithout having to rewrite or add route for each new ressources.
So I'll be interested in comparing the two method to bench them a little bit.
I'm currently moving a project from Pylons 1.0 to Pyramid.
My problem so far is how to use restful routes in Pyramid. I'm currently using pyramid_handlers since it seemed like a good start. I'm using Akhet.
So here is the two important lines in my route:
config.add_handler("new_account", "/accounts/new", "sproci2.handlers.accounts:Accounts")
# or
config.add_handler("new_account", "/accounts/new", "sproci2.handlers.accounts:Accounts", action="new")
My action:
#action(name="new_account", renderer='accounts/new.mako', request_method='GET')
The errors:
TypeError: 'Accounts' object is not callable
or
ValueError: Could not convert view return value "{}" into a response Object.
Accounts... so far so good, it is easy to understand that pyramid_handlers doesn't seem to register normally or handle name as it should... that said in request.matched_route, I do have "new_account".
If I add "action='new'" in the route definition, it will find the function but it will not listen to the action definition. In other words, it will fail to find a renderer and expect a response object. The request_method parameter doesn't actually do anything yet, so removing it doesn't change any results.
In short, the #action(name="..." doesn't work. Pyramid fails to find the function by itself and if the function name is defined it fails to execute the action statement.
No idea what I'm doing wrong.
Correct way to do it.
config.add_handler("new_account", "/accounts/new", "sproci2.handlers.accounts:Accounts", action="new_account")
EDIT
route_name is probably going to get used by url generator functions. While action is the actual name in #action. As I understood, #action name was the route_name and not the action name. That makes more sense now.
Well a call to add_handler needs an action pattern. So that's either adding {action} to the url pattern, or setting action= as an argument. Those actions must match the names defined in #action decorators. In your example, you named the action new_account, yet you called add_handler with an action of new. Thus they aren't properly connected.