Django NoReverseMatch Exception for regular expression matching 2 routes - python

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.

Related

Python Django url method regex for comma separated string in single quotes

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

Check if a parameter exists in Django URL

I am trying to get a URL if it exists in the URL but keep getting the following error:
django.utils.datastructures.MultiValueDictKeyError: 'sc'
The case is that the urls can be sometimes like the following:
/allot-graph/
and sometimes:
/allot-graph/?sc='foo'
and in my function I am doing this:
class AllotmentbyMonth(APIView):
def get(self, request):
q = request.GET['sc']
if q:
print("q", q)
dataset = some query
else:
dataset = some query
When a URL is like /allot-graph/?sc='foo', you would use q=request.GET.get('sc' , '').
sc is the parameter you want, and '' is the default value if sc isn't found.
Another way to proceed is to use URLconf, then your captures from the regex are passed to the function as arguments (or named arguments).
Such as:
(r'^ allot-graph/(?P< sc >\w{0,50})/$', views.profile_page,)
Then in your views.py you would have
def profile_page(request, sc):
# Rest of the method

NoReverseMatch in test

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

Flask redirect to url and pass query strings

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.

Handle optional url parameter in Django unit test case

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.

Categories

Resources