I had used unquote in my urls before to get special characters in the url like so:
path('example/<str:phone_number>', views.find_user_by_phone_number.as_view(), name='api.find_user_by_phone_number'),
#call with example/+849323212231
and in my views:
from urllib.parse import unquote
.....
phone_number = unquote(phone_number)
print(phone_number)
It worked great and i got +849323212231 with special character +
But now i need to make url with multiple parameters that can has phone_number in it:
path('example', views.find_user_by_phone_number.as_view(), name='api.find_user_by_phone_number'),
#call with example?phone_number=+849323212231
With view to handle parameter:
...
phone_number = unquote(request.GET.get('phone_number'))
print(phone_number)
And the result from the print i got was " 849323212231" with whitespace at the start.
Seems like value from request.GET.get('phone_number') return " 849323212231" so plus turned into whitespace.
Expected to get +849323212231 from request.GET.get('phone_number')
How do i get special character with named parameter in url ?
Related
We are using axios to pass GET request to our django instance, that splits it into search terms and runs the search. This has been working fine until we ran into an edge case. We use urlencode to ensure that strings do not have empty spaces or others
So generalize issue, we have TextField called "name" and we want to search for term "A & B Company". However, issue is that when the request reaches django.
What we expected was that name=A%20&%20B%20Company&field=value would be parsed as name='A & B Company' and field='value'.
Instead, it is parsed as name='A ' 'B Company' and field='value'. The & symbol is incorrectly treated as separator, despite being encoded.
Is there a way to indicate django GET parameter that certain & symbols are part of the value, instead of separators for fields?
You can use the lib urllib
class ModelExample(models.Model):
name = models.TextField()
# in view...
from urllib.parse import parse_qs
instance = ModelExample(name="name=A%20&%20B%20Company&field=value")
dict_qs = parse_qs(instance.name)
dict_qs contains a dict with decoded querystring
You can find more informations about urllib.parse here: https://docs.python.org/3/library/urllib.parse.html
Whenever I try to to get my query string parameter everything works but only + sign gets stripped.
Here is url file:
urlpatterns = [
re_path(r'^forecast/(?P<city>[\w|\W]+)/$', weather_service_api_views.getCurrentWeather)]
Here is view File:
#api_view(['GET'])
def getCurrentWeather(request, city):
at = request.GET["at"]
print(at)
return JsonResponse({"status": "ok"}, status=200)
So if I hit the server with this URL:
http://192.168.0.5:8282/forecast/Bangladesh/?at=2018-10-14T14:34:40+0100
the output of at is like this:
2018-10-14T14:34:40 0100
Always + sign gets stripped. No other characters get stripped. I have used characters like !, = , - etc.
Since + is a special character, you will have to encode your value. Where to encode? it depends how are you generating the values for at. Based on your URL's and endpoints it looks like you are working on a weather app and at value is generated by Javascript. You can encode your values with encodeURIComponent
let at = encodeURIComponent(<your_existing_logic>)
eg:
let at = encodeURIComponent('2018-10-14T14:34:40+0100')
it will return a result
'2018-10-14T14%3A34%3A40%2B0100'
then in your backend you can get that value with:
at = request.GET.get('at')
it will give you the desired value, 2018-10-14T14:34:40+0100 in this case.
If you are creating your at param in your backend, then there are multiple ways to achieve that. You can look into this solution:
How to percent-encode URL parameters in Python?
I'm getting a NoReverseMatch error when I try to pass two arguments from one view to another. Here is the view that is passing the arguments:
# promotion/views.py
def enter_promo_code(request, template):
if request.method == "POST":
form = PromotionCodeForm(request.POST)
if form.is_valid():
message_text, expiry_date = process_valid_promo_code(request.user, form.cleaned_data['promo_code'])
return HttpResponseRedirect(reverse('welcome-page-promo', \
kwargs={'message_text': message_text, 'expiry_date': expiry_date}))
else:
form = PromotionCodeForm(label_suffix="")
context = {'form': form}
return render(request, template, context)
Here is the receiving view. Note that the two input arguments are optional. The urlpatterns show that this view can be called with or without arguments.
# home/views.py
def welcome_page(request, template, message_text=None, expiry_date=None):
account = Account.objects.get(pk=request.user.id)
context = {'uid': request.user.id, 'account_type': account.type.account_type_cd, 'message_text': message_text, 'expiry_date': expiry_date}
return render(request, template, context)
Here are the urlpatterns for the receiving view:
# home/urls.py
url(r'^welcome/$',
'home.views.welcome_page',
{'template': 'welcome_page.html'},
name='welcome-page'),
url(r'^welcome/(?P<message_text>\w{1,})/(?P<expiry_date>\w{1,})/$',
'home.views.welcome_page',
{'template': 'welcome_page.html'},
name='welcome-page-promo'),
When I execute the promotion view, I get this error when the return HttpResponseRedirect command executes:
NoReverseMatch at /promotion/code/
Reverse for 'welcome-page-promo' with arguments '()' and keyword arguments '{'message_text': u'Your promotion code was approved! You will receive a one-year free trial membership which expires on ', 'expiry_date': 'Jul. 18, 2018'}' not found. 1 pattern(s) tried: ['welcome/(?P<message_text>\\w{1,})/(?P<expiry_date>\\w{1,})/$']
I'm running this same code pattern in a different application in the project and it runs without error. Can anyone see what I'm doing wrong?
You have two problems here, one of design and one of implementation.
The design problem is that you probably shouldn't have such long text in your URLs. I believe Django will handle the argument escaping for you, but it's still not going to be the easiest pattern to work with. It looks to me like your message_text argument is likely to be static, or at least selected from a small number of possibilities. Most likely you should record it in your template, create a model for it and pass around the ID, or something along those lines. There's nothing wrong with passing dates around in a URI, although I prefer a simpler format like 2018-07-18 over Jul. 18, 2018, but if it's truly an expiration date you probably want to have a model for memberships and set it as an attribute there, then look it up it your welcome page view.
Putting that aside and looking at your implementation problem - your view regexps only match one or more characters from the \w class, which is defined as:
When the LOCALE and UNICODE flags are not specified, matches any alphanumeric character and the underscore; this is equivalent to the set [a-zA-Z0-9_]. With LOCALE, it will match the set [0-9_] plus whatever characters are defined as alphanumeric for the current locale. If UNICODE is set, this will match the characters [0-9_] plus whatever is classified as alphanumeric in the Unicode character properties database.
However, your args include characters like ! and spaces. Use a regexp that matches your desired arguments - [^/]+ is one, if you want to be forgiving. (+ is more readable than {1,} in my opinion, but they mean the same thing.)
I am using Django 1.5 and trying to pass args to my URL. When I use the first two args then the below code works fine, with the third args I am getting an error. I have already referred to the new Django 1.5 update for url usage and accordingly used quotes for the URL name.
NoReverseMatch: Reverse for 'add_trip' with arguments '()' and keyword arguments '{u'city': 537, u'score': 537, u'time': 35703, u'distance': 1196.61}' not found
urls.py
url(
r'^add/(?P<city>\w+)/(?P<score>\w+)/(?P<distance>\w+)/(?P<time>\w+)$',
'trips.views.add_trip',
name='add_trip'
),
html file
Add/delete
If I use only two args (i.e city and score, then it works fine) else I get the no reverse match error.
views.py
def SearchTrips(request):
city = request.POST['city'].replace(" ","%20")
location = request.POST['location'].replace(" ","%20")
duration = request.POST['duration']
#url = "http://blankket-mk8te7kbzv.elasticbeanstalk.com/getroutes?city=%s&location=%s&duration=%s" % (city, location, duration)
url= "http://blankket-mk8te7kbzv.elasticbeanstalk.com/getroutes?city=New%20York%20City&location=Park%20Avenue&duration=10"
print url
try:
resp = urllib2.urlopen(url)
except:
resp = None
if resp:
datas = json.load(resp)
else:
datas = None
return render(request, 'searchtrips.html', {'datas': datas})
The distance value 1196.61 does not match the regex because of the decimal point.
You can use
(?P<distance>[\w\.]+)
which matches uppercase A-Z, lowercase a-z, digits 0-9, hyphens and decimal points.
Alternatively, you could use
(?P<distance>[\d\.]+)
Which only matches digits 0-9 and decimal points.
In Django what is the url pattern I need to use to handle urlencode characters such as %20
I am using (?P<name>[\w]+) but this only handles alphanumeric characters so % is causing an error
I was able to make it work using the configuration given below. Check if it will suit your needs.
(?P<name>[\w|\W]+)
If you only want to allow space:
(?P<name>[\w\ ]+)
The best way to do that and allow others chars is using '\s' that is any spaces, tabs and new lines
(?P<name>[\w\s]+)
I am using Django 2.2.
It handles the %20 (which means space) in url using Path converter: str
You simply need to use:
<name> or <str:name>
For example, following example loads view "some_view" defined in view.py
#urls.py
from django.urls import path
from . import views
urlpatterns = [
path("<name>",views.some_view),
....
]
The following function renders "some.html" after processing. In this example sending the received name to "some.html".
#view.py
def some_view(request, name):
# process here
context = { "name" : name }
return render(request,"some.html",context)