Django request.GET.get() always returns "None" - regex

I have a URL: http://localhost:8000/submit_workout/2/
This URL was created with: r'^submit_workout/(?P<wr_id>\d+)/$'
I am trying to retrieve "wr_id" when a form on that page is submitted.
I'm trying: wr_id = request.GET.get('wr_id',None) and am expecting wr_id=2 but keep getting wr_id=None returned.
Any thoughts? I am new to programming/django and really appreciate your time and expertise.

URL params, which are named in the url regex, can be passed as arguments to your method which handles the request. If your dispatcher looks like this:
urlpatterns = patterns('',
(r'^submit_workout/(?P<wr_id>\d+)/$', 'submit_workout'),
Then your method should look like this:
def submit_workout(request, wr_id):
and wr_id can be accessed directly.
If you want wr_id to be a GET variable, then your url should look like this:
http://localhost:8000/submit_workout?wr_id=2

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.

how to create params in django url?

I have a django project where url is like this
url(r'^invoice/(?P<invoice_id>[A-Za-z0-9]+)/(?P<order_id>[A-Za-z0-9]+)$',GenerateInvoicePdf,name='invoice'),
which generates url localhost:8000/invoice/2341wq23fewfe1231/3242
but i want url to be like localhost:8000/invoice?invoice_id=2341wq23fewfe1231&order_id=3242
i tried documentation and used syntax like this re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), But did not get desired result.
how can i do so?
The parts which you are trying to write after ? is called url query string. You don't need to define them in the urls.py. You can just use:
re_path(r'^comments/$', comments),
And inside comments views, you can access the query string like this:
def comments(request):
invoice_id = request.GET.get('invoice_id')
order_id = request.GET.get('order_id')
# rest of the code

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.

Reverse Not Found: Sending Request Context in from templates

N.B This question has been significantly edited before the first answer was given.
Hi,
I'm fairly new to django, so apologies if I'm missing something obvious.
I've got a urls.py file that looks like this:
urlpatterns = patterns(
'',
(r'^$', 'faros.lantern.views.home_page'),
(r'^login/$', 'django.contrib.auth.views.login'),
(r'^logout/$', 'django.contrib.auth.views.logout'),
(r'^about/$', 'faros.lantern.views.about_page_index', {}, 'about_page_index'),
(r'^about/(?P<page_id>([a-z0-9]+/)?)$', 'faros.lantern.views.about_page', {}, 'about_page'),
)
Views that looks like this:
def about_page_index(request):
try:
return render_to_response('lantern/about/index.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
def about_page(request, page_id):
page_id = page_id.strip('/ ')
try:
return render_to_response('lantern/about/' + page_id + '.html', context_instance=RequestContext(request))
except TemplateDoesNotExist:
raise Http404
And a template that includes this:
Contact
Contact
I'm getting this error message:
Caught an exception while rendering: Reverse for '<function about_page at 0x015EE730>' with arguments '()' and keyword arguments '{'page_id': u'contact'}' not found. The first reverse works fine (about_page_index), generating the correct URL without error messages.
I think this is because the request argument to the about_page view (request) is used, so I need to pass it in when I generate the URL in my template. Problem is, I don't know how to get to it, and searching around isn't getting me anywhere. Any ideas?
Thanks,
Dom
p.s. As an aside, does that method of handling static "about" type pages in an app look horrific or reasonable? I'm essentially taking URLs and assuming the path to the template is whatever comes after the about/ bit. This means I can make the static pages look like part of the app, so the user can jump into the about section and then right back to where they came from. Comments/Feedback on whether this is djangoic or stupid appreciated!
If I guess correctly from the signature of your view function (def about_page(request, page_id = None):), you likely have another URL configuration that points to the same view but that does not take a page_id parameter. If so, the django reverse function will see only one of these, and it's probably seeing the one without the named page_id regex pattern. This is a pretty common gotcha with reverse! :-)
To get around this, assign a name to each of the url patterns (see Syntax of the urlpatterns variable). In the case of your example, you'd do:
(r'^about/(?P<page_id>([a-z]+/)?)$', 'faros.lantern.views.about_page',
{}, 'about_with_page_id')
and then in the template:
Contact
Edit
Thanks for posting the updated urls.py. In the url template tag, using the unqualified pattern name should do the trick (note that I'm deleting the lantern.views part:
Contact
Contact
Edit2
I'm sorry I didn't twig to this earlier. Your pattern is expressed in a way that django can't reverse, and this is what causes the mismatch. Instead of:
r'^about/(?P<page_id>([a-z]+/)?)$'
use:
r'^about/(?P<page_id>[a-z0-9]+)/$'
I created a dummy project on my system that matched yours, reproduced the error, and inserted this correction to success. If this doesn't solve your problem, I'm going to eat my hat! :-)

Capturing URL parameters in request.GET

I am currently defining regular expressions in order to capture parameters in a URL, as described in the tutorial. How do I access parameters from the URL as part the HttpRequest object?
My HttpRequest.GET currently returns an empty QueryDict object.
I'd like to learn how to do this without a library, so I can get to know Django better.
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
To clarify camflan's explanation, let's suppose you have
the rule url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
an incoming request for http://domain/user/thaiyoshi/?message=Hi
The URL dispatcher rule will catch parts of the URL path (here "user/thaiyoshi/") and pass them to the view function along with the request object.
The query string (here message=Hi) is parsed and parameters are stored as a QueryDict in request.GET. No further matching or processing for HTTP GET parameters is done.
This view function would use both parts extracted from the URL path and a query parameter:
def profile_page(request, username=None):
user = User.objects.get(username=username)
message = request.GET.get('message')
As a side note, you'll find the request method (in this case "GET", and for submitted forms usually "POST") in request.method. In some cases, it's useful to check that it matches what you're expecting.
Update: When deciding whether to use the URL path or the query parameters for passing information, the following may help:
use the URL path for uniquely identifying resources, e.g. /blog/post/15/ (not /blog/posts/?id=15)
use query parameters for changing the way the resource is displayed, e.g. /blog/post/15/?show_comments=1 or /blog/posts/2008/?sort_by=date&direction=desc
to make human-friendly URLs, avoid using ID numbers and use e.g. dates, categories, and/or slugs: /blog/post/2008/09/30/django-urls/
Using GET
request.GET["id"]
Using POST
request.POST["id"]
Someone would wonder how to set path in file urls.py, such as
domain/search/?q=CA
so that we could invoke query.
The fact is that it is not necessary to set such a route in file urls.py. You need to set just the route in urls.py:
urlpatterns = [
path('domain/search/', views.CityListView.as_view()),
]
And when you input http://servername:port/domain/search/?q=CA. The query part '?q=CA' will be automatically reserved in the hash table which you can reference though
request.GET.get('q', None).
Here is an example (file views.py)
class CityListView(generics.ListAPIView):
serializer_class = CityNameSerializer
def get_queryset(self):
if self.request.method == 'GET':
queryset = City.objects.all()
state_name = self.request.GET.get('q', None)
if state_name is not None:
queryset = queryset.filter(state__name=state_name)
return queryset
In addition, when you write query string in the URL:
http://servername:port/domain/search/?q=CA
Do not wrap query string in quotes. For example,
http://servername:port/domain/search/?q="CA"
def some_view(request, *args, **kwargs):
if kwargs.get('q', None):
# Do something here ..
For situations where you only have the request object you can use request.parser_context['kwargs']['your_param']
You have two common ways to do that in case your URL looks like that:
https://domain/method/?a=x&b=y
Version 1:
If a specific key is mandatory you can use:
key_a = request.GET['a']
This will return a value of a if the key exists and an exception if not.
Version 2:
If your keys are optional:
request.GET.get('a')
You can try that without any argument and this will not crash.
So you can wrap it with try: except: and return HttpResponseBadRequest() in example.
This is a simple way to make your code less complex, without using special exceptions handling.
I would like to share a tip that may save you some time.
If you plan to use something like this in your urls.py file:
url(r'^(?P<username>\w+)/$', views.profile_page,),
Which basically means www.example.com/<username>. Be sure to place it at the end of your URL entries, because otherwise, it is prone to cause conflicts with the URL entries that follow below, i.e. accessing one of them will give you the nice error: User matching query does not exist.
I've just experienced it myself; hope it helps!
These queries are currently done in two ways. If you want to access the query parameters (GET) you can query the following:
http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1
If you want to access the parameters passed by POST, you need to access this way:
request.data.get('role', None)
Accessing the dictionary (QueryDict) with 'get()', you can set a default value. In the cases above, if 'status' or 'role' are not informed, the values ​​are None.
If you don't know the name of params and want to work with them all, you can use request.GET.keys() or dict(request.GET) functions
This is not exactly what you asked for, but this snippet is helpful for managing query_strings in templates.
If you only have access to the view object, then you can get the parameters defined in the URL path this way:
view.kwargs.get('url_param')
If you only have access to the request object, use the following:
request.resolver_match.kwargs.get('url_param')
Tested on Django 3.
views.py
from rest_framework.response import Response
def update_product(request, pk):
return Response({"pk":pk})
pk means primary_key.
urls.py
from products.views import update_product
from django.urls import path
urlpatterns = [
...,
path('update/products/<int:pk>', update_product)
]
You might as well check request.META dictionary to access many useful things like
PATH_INFO, QUERY_STRING
# for example
request.META['QUERY_STRING']
# or to avoid any exceptions provide a fallback
request.META.get('QUERY_STRING', False)
you said that it returns empty query dict
I think you need to tune your url to accept required or optional args or kwargs
Django got you all the power you need with regrex like:
url(r'^project_config/(?P<product>\w+)/$', views.foo),
more about this at django-optional-url-parameters
This is another alternate solution that can be implemented:
In the URL configuration:
urlpatterns = [path('runreport/<str:queryparams>', views.get)]
In the views:
list2 = queryparams.split("&")
url parameters may be captured by request.query_params
It seems more recommended to use request.query_params. For example,
When a URL is like domain/search/?q=haha, you would use request.query_params.get('q', None)
https://www.django-rest-framework.org/api-guide/requests/
"request.query_params is a more correctly named synonym for request.GET.
For clarity inside your code, we recommend using request.query_params instead of the Django's standard request.GET. Doing so will help keep your codebase more correct and obvious - any HTTP method type may include query parameters, not just GET requests."