I get this error in one of my tests:
NoReverseMatch: Reverse for 'plan' with arguments '()' and
keyword arguments '{u'month': u'201604'}' not found.
1 pattern(s) tried: ['plan(/(?P<month>[0-9]+))?$']
The call was
response = self.client.get(reverse('plan', kwargs={'month': '201604'}))
and the urlpattern
url(r'^plan(/(?P<month>[0-9]+))?$', sp_views.plan, name='plan'),
I tried to call /plan/201604 without hardcoding the url. What have I done wrong?
You need to make the outer argument non-capturing:
url(r'^plan(?:/(?P<month>[0-9]+))?$', text, name='plan'),
Personally, I always find this confusing, so I prefer to have two url patterns. I would include a trailing slash in the urls as well:
url(r'^plan/$', sp_views.plan, name='plan'),
url(r'^plan/(?P<month>[0-9]+)/$', sp_views.plan, name='plan'),
Related
Attempting to regex match a string like so:
'1,2'
Using Django rest framework url method to parse incoming string, I tried this:
url(r'^path/to/api/end_point/(?P<player_ids>"\'1,2\'")/',
PlayerResultsView.as_view(),
name='get_players)
The error I get:
django.core.urlresolvers.NoReverseMatch: Reverse for 'get_players'
with arguments '()' and keyword arguments '{'player_ids': '1,2'}' not
found. 1 pattern(s) tried:
['path/to/api/end_point/(?P<player_ids>"\'1,2\'")/']
Overall Goal: pass comma separated string ('1,2,3,4') to REST endpoint, split on the comma and continue processing.
Solution 1
What you are trying to do is match a fixed string 1,2. If you want a variable input whether it is 1,2 or 1,2,3,4 or others, then try this regex pattern [\d,]+ which will capture non-empty string containing any numbers and commas.
re_path(r'^path/to/api/end_point/(?P<player_ids>[\d,]+)/', views.some_view),
Sample URL would be:
http://127.0.0.1:8000/path/to/api/end_point/1,2,3,4/
Solution 2
Instead of such variable input in the path, you might be interested in making it query parameters instead. So something like:
path('path/to/api/end_point/', views.some_view),
Sample URL would be:
http://127.0.0.1:8000/path/to/api/end_point/?player_ids=1,2,3,4
Then, just access it as part of the request.GET or request.query_params (if using djangorestframework) in your view.
def some_view(request, **kwargs):
print(f"{request.GET.get('player_ids')=}")
print(f"{request.query_params.get('player_ids')=}")
Output
request.GET.get('player_ids')='1,2,3,4'
request.query_params.get('player_ids')='1,2,3,4'
[08/Sep/2021 01:44:05] "GET path/to/api/end_point/?player_ids=1,2,3,4 HTTP/1.1" 200 17
I decided to go with a POST, easier to pass more complex parameters.
My URL pattern:
url(r'^path/to/api/end_point/',
PlayerResultsView.as_view(),
name='get_players)
My POST data is an array of player ids:
list_of_search_ids = [player1.player_id, player2.player_id]
data = {'player_ids': list_of_search_ids}
url = reverse(
"get_players"
)
resp = self.client.post(url, json.dumps(data), content_type='application/json')
I'm trying to inspect a request's argument before the get() is invoked. I have a route which is described as so:
user_route = r"/users/key=(?P<key>\w+)"
app = web.Application([
web.URLSpec(user_route, user_manager.UserHandler), ..])
Next, (in the handler) prepare() is used to inspect the request before get().
def prepare(self):
# inspect request arguments
print(self.request.arguments) # prints "{}"
The problem I'm having is that I cannot access the arguments from prepare(). The last statement prints an empty dict. My get() successfully uses the arguments as they are passed in the function like this:
def get(self, key):
print(key) #works
How do I access arguments in prepare()? I have also tried self.argument('key') which gives an error "400 GET .... Missing argument key", but requested URL does have a key argument in it.
In your code key is not a GET-argument, it's a part of a path. tornado.we.URLSpec passes any capturing groups in the regex into the handler’s get/post/etc methods as arguments.
tornado.web.RequestHandler has RequestHandler.path_args and RequestHandler.path_kwargs which contain the positional and keyword arguments from URLSpec. Those are available in prepare method:
def prepare(self):
# inspect request arguments
print(self.path_kwargs) # prints {"key": "something"}
As Gennady Kandaurov mentioned, you passed the key as a part of the we.URLSpec path and you can access it using Tornado's self.path_kwargs. If you wanted to pass it as an argument you could used RequestHandler.get_argument to get the argument on your get method and use self.request.arguments on your prepare method to access it as your initial intention.
Your code could be as follow:
class Application(tornado.web.Application):
def __init__(self):
user_route = r"/users"
app = tornado.web.Application([
tornado.web.url(user_route, user_manager.UserHandler), ..])
class UserHandler(tornado.web.RequestHandler):
def get(self):
key = self.get_argument('key')
print(key)
def prepare(self):
# inspect request arguments
print(self.request.arguments)
Please let me know if you have any further question.
It's generally bad to use a character like = in a URL path fragment, since they are generally used for query arguments. Either don't use it:
`r"/users/(?P<key>\w+)"`
or turn it into a proper query argument
`r"/users/\?key=(?P<key>\w+)"`
Otherwise it's confusing for a maintainer to try to figure out which scheme you intended to use (did you really want to route a path fragment called /key%3D\w+? Or did you really mean you wanted a query arg and forgot the ??)
In any case, for URL path fragment matching ("slug-matching"), using argument unpacking can let you access them in the handler too, without having to invoke path_kwargs:
# `r"/users/(?P<key>\w+)"`
class Handler(RequestHandler):
def get(self, **kwargs):
key = kwargs.get('key')
# I prefer dict.get() here, since if you change the `+` to a `*`,
# it's possible that no key was supplied, and kwargs['key']
# will throw a KeyError exception
If you intended to use a query argument for key, then #afxentios's answer is appropriate. (You can also use self.get_query_argument('key') which will explicitly only look for query arguments in the URL (whereas get_argument also checks in the request BODY for a www-url-encoded argument (such as if you POST)).
url(r'^v1/(statistics|analytics)/stats_bar$', views.stats_bar, name='stats_bar')
reverse('stats_bar')
Throws: Reverse for 'stats_bar' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['v1/(statistics|analytics)/stats_bar$']
Is there any way to manipulate the pattern Django tries or another simple way to deal with this issue?
Django==1.6.9
I think django is interpreting (statics|analytics) as a pattern for variable. I suggest as follow:
define 2 different url to the same view:
url(r'^v1/statistics/stats_bar$', views.stats_bar, name='stats_bar_statistics')
url(r'^v1/analytics/stats_bar$', views.stats_bar, name='stats_bar_analytics')
reverse('status_bar_statistics') # usage
and inside the view test which url has been used:
if 'analytics' in request.path:
# do something
elif 'statistics' in request.path:
# do otherthing
you define one url with parameter:
url(r'^v1/ (?P<type>(statistics|analytics))/stats_bar$', views.stats_bar, name='stats_bar')
reverse('status_bar', kwargs={'type': 'statistics'}) # usage
https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse
Look at the section about args.
I have a view that is defined like such:
#views.route('/issues')
def show_view():
action = request.args.get('action')
method = getattr(process_routes, action)
return method(request.args)
in my process_routes module, I would like to call this method, and pass query string values. I have the following code:
return redirect(url_for('views.show_view', action='create_or_update_success'))
I have a function in process_routes named create_or_update_success
I am getting
BuildError: ('views.show_view', {'action': 'create_or_update_success'}, None)
views is a blueprint. I can successfully call
/issues?action=create_or_update_success
In my browser.
What am I doing wrong?
The first part, views., has to reflect the first argument you give to your Blueprint() object exactly.
Don't be tempted to set that first argument to __name__, as that is likely to contain the full path of the module when inside a package. In your case I suspect that to be some_package.views rather than just views.
Use a string literal for the Blueprint() first argument instead:
views_blueprint = Blueprint('views', __name__)
so you can refer to url_for('views.show_view') without getting build errors.
I have created a Dynamic Url with optional parameter
e.g., If my url is as www.example.com/getTest/1/
Now this 1 in url is optional , to handle this in views I have used None like
def function(request, id=None):
pass
Thus if there is no id in URL then still the function works for me.
But I am facing issue while testing this in unit cases.
if I use url as url = reverse('yescourse:academypage_url', args=[None]) it gives me the error
NoReverseMatch: Reverse for 'academypage_url' with arguments '('new', None)' and keyword arguments '{}' not found.
So Please Tell me how I can handle these optional url in Test cases or in Reverse.
Edit :
url(r'^getTest/(?P<action>\w+)/(?P<id>\d*)$', 'app.views.create_edit_academypage', name='academypage_url'),
You made the view function's id parameter optional, but it's not optional in the url pattern. You firsty need to rewrite your pattern as :
r'^getTest/(?P<action>\w+)/(?P<id>\d+)?$'
=> the whole 'id' sub-pattern is optional, but if it's not it must match one or more numerics.
Once done, you can reverse the url by not passing any of the args nor kwargs arguments:
url = reverse('yescourse:academypage_url')
or by passing an empty list
url = reverse('yescourse:academypage_url', args=[])
or by passing None
url = reverse('yescourse:academypage_url', args=None)
but not by passing a list containing None.