Django query param get stripped if there is (+) sign - django

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?

Related

How to pass # in url as a parameter in django 2

I am trying to pass a code "Req-2019#000001" Django URL. I want to pass this code as well as normal string and number also in URL as arguments.
path('generateBomForSingleProduct/<requisition_no>/' , views.generateBomForSingleProduct, name='generateBomForSingleProduct'),
Its work properly but the problem is its add extra / before #
My URL is now this
http://127.0.0.1:8000/production/generateBomForSingleProduct/Req-2019/#000001
But I want to like this
http://127.0.0.1:8000/production/generateBomForSingleProduct/Req-2019#000001
Not an extra "/" before my "#"
The portion of the URL which follows the # symbol is not normally sent to the server in the request for the page. So, it's not possible to have a URL as /production/generateBomForSingleProduct/Req-2019#000001
Workaround
Just modify the url as /production/generateBomForSingleProduct/Req-2019/000001, so you need to modify the view also
# views.py
def generateBomForSingleProduct(request, part_1, part_2):
unique_id = "{}#{}".format(part_1, part_2)
# use the "unique_id"
...
#urls.py
urlpatterns = [
...,
path('foo/<part_1>/<part_2>/', generateBomForSingleProduct, name="some-name"),
...
]
Using 'get' would be the proper way to do this. # is for html fragments, which are not sent to the server. Why can't it just be
/production/generateBomForSingleProduct/Req-2019?code=000001 and then you handle everything in the view that way?
Part after # is called fragment identifier, which is used by browsers and never sent to server.
In http://127.0.0.1:8000/production/generateBomForSingleProduct/Req-2019/#000001 url 000001 is never sent to server. Hence using important part of url after # is useless. Better to pass 000001 as query parameters or separate argument.

What would be Djnago's url pattern to match and fetch out a url (coming appended to site's domain as a GET request)?

Suppose my site's domain is mysite.com , now whenever a request comes in this form : mysite.com/https://stackoverflow.com :I want to fetch out this url "https://stackoverflow.com" and send it to the corresponding view.
I have tried this pattern :
url(r'^(?P<preurl>http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)$',prepend_view)
regex of which matches the incoming appended url and assigns variable preurl the value "https://stackoverflow.com", which I access in corresponding view function .
This works fine for above example but my url pattern is failing in case of some exceptional urls..
Please suggest a robust url pattern by taking into consideration all exceptional urls too, like the following:
ftp://ftp.is.co.za/rfc/rfc1808.txt
http://www.ietf.org/rfc/rfc2396.txt
ldap://[2001:db8::7]/c=GB?objectClass?one
mailto:John.Doe#example.com
news:comp.infosystems.www.servers.unix
tel:+1-816-555-1212
telnet://192.0.2.16:80/
urn:oasis:names:specification:docbook:dtd:xml:4.1.2
That is, if a request comes like :
mysite.com/ldap://[2001:db8::7]/c=GB?objectClass?one
I should be able to get the value "ldap://[2001:db8::7]/c=GB?objectClass?one" in variable preurl
You don't have to make this type of complex url pattern, First, make a URL pattern that matches everything.
url(r'^.*/$', views.fast_track_service, name='fast_track'),
and append it to the end in urlpatterns in your urls.py then in your view, Use request object, So You can get the full path of get request with this method,
fast_track_url = request.get_full_path()[1:]
and then once you got the url try validating that with URLValidator like this.
if not 'http://' in fast_track_url and not 'https://' in fast_track_url:
fast_track_url = 'http://' + fast_track_url
url_validate = URLValidator()
try:
url_validate(fast_track_url)
except:
raise Http404
If you want to validate other complicated URL like mailto etc, then you can write your own validator.

Why does urllib2 not take my URL?

I have got URLs stored in a list which are supposed to be passed to urllib2. However, urllib doesn't seem to like this very much and I just cannot see why!
here is what I have got:
url = list[1]
response = urllib2.urlopen(url)
html = response.read()
The URL is a google maps Directions Web API URL of the kind:
http://maps.googleapis.com/maps/api/directions/json?origin=[origin]&destination=[destination]&waypoints=optimize:true|[waypoint1]|[waypoint2]&sensor=false
Now, if I try to run this, the retrieved html always looks something like this:
{
"routes" : [],
"status" : "INVALID_REQUEST"
}
Indicating that something is wrong with the passed URL. If however, I take the URL and assign it directly, like so:
url = "http://maps.googleapis.com/maps/api/directions/json?origin=[origin]&destination=[destination]&waypoints=optimize:true|[waypoint1]|[waypoint2]&sensor=false"
response = urllib2.urlopen(url)
html = response.read()
The result will happily come through with the (for me) essential end part looking like this:
"warnings" : [],
"waypoint_order" : [ 2, 0, 7, 5, 6, 4, 3, 1 ]
}
],
"status" : "OK"
}
My (hopefully not too stupid) question is therefore: why does urllib do its job when the URL is assigned directly but not if it comes from a list??
Thank you very much for your help,
J
PS: Is there a reason why the forum-software always cuts off my 'Hi all' greeting?
I have finally resolved the issue!
Was pretty easy once I stepped back for a moment and thought about it again:
I did get an answer from google's Web API which means that urllib2 did pass something. However, it must have been sending something that didn't make any sense to the API backend. The URL containing German addresses I lucky-guessed the problem being caused by umlauts.
So I simply passed my URL through a function replacing each umlaut with its non-umlaut alternative and suddenly everything seemed to work fine.
If anybody comes accross a similar issue, here's how I solved it:
# Function for replacing all umlauts
def replaceUmlauts(text):
dic = {'Ä':'Ae', 'ä':'ae', 'Ö':'Oe', 'ö':'oe', 'Ü':'Ue', 'ü':'ue', 'ß':'ss'}
for i, j in dic.iteritems():
text = text.replace(i, j)
return text
Then simply use
response = urllib2.urlopen(replaceUmlauts(url))

Django: grabbing parameters

I'm having the hardest time with what should be super simple. I can't grab the passed parameters in django.
In the browser I type:
http://localhost:8000/mysite/getst/?term=hello
My url pattern is:
(r'^mysite/getst/$', 'tube.views.getsearchterms')
My View is
def getsearchterms(request):
my_term = some_way_to_get_term
return HttpResponse(my_term)
In this case it should return "hello". I am calling the view, but a blank value is returned to me. I've tried various forms of GET....
What should some_way_to_get_term be?
The get parameters can be accesses like any dictionary:
my_term = request.GET['term']
my_term = request.GET.get('term', 'my default term')
By using arbitrary arguments after ? and then catching them with request.GET['term'], you're missing the best features of Django urls module : a consistent URL scheme
If "term" is always present in this URL call it must be meaningful to your application,
so your url rule could look like :
(r'^mysite/getst/(?P<term>[a-z-.]+)/', 'tube.views.getsearchterms')
That means :
That you've got a more SEO-FRIENDLY AND stable URL scheme (no ?term=this&q=that inside)
That you can catch your argument easily in your view :
Like this
def getsearchterms(request,term):
#do wahtever you want with var term
print term

Force query parameters to be matched in urls.py

I want the WHOLE url after the slash to be passed to a script. If I do :
url(r'^(?P<id>.*)$', alias.get, name="alias"),
Then I only get the path component and not the query parameters passed to my function. I then have to :
def urlencode(dict) :
if len(dict) == 0 : return ""
params = {}
for k, v in dict.items() :
params[k] = v.encode('utf-8')
return "?" + urllib.urlencode(params)
def get(id) :
id += urlencode(request.GET)
I am doing this for a lot of my views and I keep forgetting it and creating bugs. Is there any way to tell my urls.py to match everything including the query string?
Inside your view, you can get the URL including the query string with request.get_full_path().
There's also request.build_absolute_uri() if you want to include the http://servername.com part.
No, there's no way of doing that. The GET parameters aren't passed to urls.py.
I wonder why you need to do this though. Why are so many of your views dependent on GET querystrings? Why don't you use the Django way of doing things, which is to make the parameters part of the URL itself, rather than as querystrings.