json? in Django URL regex - regex

This question might reveal a gaping hole in my knowledge of json queries, but I'm trying to get json data to display on a view with the following URL.
http://localhost:8000/structures/hydrants/json?id=%3D2/
Here's my URL regex:
url(r'^hydrants/json\\?id=(?P<hydrant_id>\d+)/$', views.hydrant_json, name='hydrant_json'),
and the view:
def hydrant_json(request, hydrant_id):
hydrant = get_object_or_404(Hydrant, pk=hydrant_id)
data = [hydrant.json()]
return HttpResponse(json.dumps(data), content_type='application/json')
Obviously, the question mark is throwing it off, because if I make the regex
url(r'^hydrants/json/id=(?P<hydrant_id>\d+)/$', views.hydrant_json, name='hydrant_json'),
then the following URL will work:
http://localhost:8000/structures/hydrants/json/id%3D2/
Thanks in advance!

If you want to send the data as GET parameters, you can simply do:
url(r'^hydrants/json/$', views.hydrant_json, name='hydrant_json'),
url(r'^hydrants/json/(?P<hydrant_id>\d+)/$', views.hydrant_json, name='hydrant_json_with_key'),
and views:
def hydrant_json(request, hydrant_id=None):
if not hydrant_id:
hydrant_id = request.GET.get('id')
if not hydrant_id: #if hydrant_id is not received for some reason, throw 404.
raise Http404
hydrant = get_object_or_404(Hydrant, pk=hydrant_id)
data = [hydrant.json()]
return HttpResponse(json.dumps(data), content_type='application/json')
Here, you are defining flexible ways of sending hydrant_id into the view.
By default, for a GET request, request.GET would have all the get parameters - example: ?id=123
Also, if you want to send hydrant_id as a part of the URL, You can just do
http://localhost:8000/structures/hydrants/json/302/
Please note, 3D2 would never get matched as a URL in the regex because your URL is looking for \d+ which is digits only.

Related

How to print out request.body data in django?

Just working through the Django tutorials and playing around with stuff. Was going through the HttpResponse and HttpRequest docs and I'm just trying to print out data to see how things work.
However, when I try to print to console the request.body I get nothing back.
def detail(request, question_id):
current_question_selected = Question.objects.get(pk=question_id)
choices_for_question = current_question_selected.choice_set.all()
context = {"choices_for_question":choices_for_question, "current_question_selected":current_question_selected}
#print(request.META["REMOTE_USER"])
print(request.body)
return render(request, 'polls/detailtext.html', context)
This is what gets pritned to the screen, the letter 'b' with an empty string
[28/Jun/2022 10:59:56] "GET /polls/1/ HTTP/1.1" 200 456
b''
Not sure what i'm missing
The print displays an empty string because GET does not accept a body. Taken directly from the Mozilla Web APIs docs:
Note that a request using the GET or HEAD method cannot have a body and null is return in these cases.
If you want to pass data in a GET request, you need to pass them as parameters instead. Then, you can access the parameters using request.GET (HttpRequest.GET) or access them individually with request.GET.get('key').

Django Url pattern (add paramether), and view

There is urls.py pattern.
url(r'^notice/(?P<article>[0-9]\d+)/', web.views.notice),
Here is views.py
def notice(request, article):
data = article
return render(request, "notice.html")
However, web brower shows 404 Error.
If I remove add parameter, it is ok.
What I am wrong?
Intended result (Blog style, not get parameter)
/notice/1, /notice/2, ...
I think what is happening is that [0-9]\d+ is expecting at least a 2-digit number, one digit for the [0-9] and then one or more digits following that due to the \d+. I believe what you really want is just
url(r'^notice/(?P<article>\d+)$', 'web.views.notice')
I don't know why you use d???
url(r'^issue/(?P<issue_id>[0-9]+)$', views.issue, name='issue'),
url(r'^project/(?P<pk>.*)$', login_required(views.ProjectView.as_view()), name='project'),
Based on the question you asked, I am getting that you want to display the data on the template based on the parameter passed in the URL.Let me try to explain it step by step:
First lets say you have the following url:
url(r'^notice/(?P<article>\d+)$', views.notice,name="notice")
Now lets define the view for fetching the data from the model, based on the parameter in the URL, i am assuming you are passing the PK in the URL:
def notice(request, article):
data = YourModelName.objects.get(id=article)
//Passing back the result to the template
context={"article":data}
return render(request, "notice.html",context)
Now in your template you can access the data as such:
{{ article.field_name }}
Hope this helps you out!!!!

Django URLConf Redirect with odd characters

I'm getting ready to move an old Classic ASP site to a new Django system. As part of the move we have to setup some of the old URLs to point to the new ones.
For example,
http://www.domainname.com/category.asp?categoryid=105 should 301 to http://www.domainname.com/some-category/
Perhaps I'm regex stupid or something, but for this example, I've included in my URLconf this:
(r'^asp/category\.asp\?categoryid=105$', redirect_to, {'url': '/some-category/'}),
My thinking is that I have to escape the . and the ? but for some reason when I go to test this, it does not redirect to /some-category/, it just 404s the URL as entered.
Am I doing it wrong? Is there a better way?
To elaborate on Daniel Roseman's answer, the query string is not part of the URL, so you'll probably want to write a view function that will grab the category from the query string and redirect appropriately. You can have a URL like:
(r'^category\.asp', category_redirect),
And a view function like:
def category_redirect(request):
if 'categoryid' not in request.GET:
raise Http404
cat_id = request.GET['category']
try:
cat = Category.objects.get(old_id=cat_id)
except Category.DoesNotExist:
raise Http404
else:
return HttpResponsePermanentRedirect('/%s/' % cat.slug)
(Altered to your own tastes and needs, of course.)
Everything after the ? is not part of the URL. It's part of the GET parameters.

Handling multiple sub-urls in Django's url.py file

In my djang urls pattern file, I'd like to hold a bunch of sub-url's but I don't want to make it ugly.
I have a file which handles all of my Ajax requests (it outputs different JSON files depending on the request it gets.
example (in my url.py):
in the form: (url, maps to)
(ajax/do_a, ajax.do_a)
ajax/do_b, ajax.do_b)
ajax/do_c, ajax.do_c)
ajax/do_d, ajax.do_d)
these are all sub-urls, eg.
mywebsite.com/ajax/do_a
mywebsite.com/ajax/do_b
etc.
Basically do_a,do_b,do_c,and do_d are all different request handlers sitting in the same same in the "ajax.py" file. I really don't want to be filling up my urls.py file with all of these urls for ajax requests. I was thinking of move this so that I only have
ajax/
in my url.py file and then somehow parse the ajax/ request url in my request handler (in the ajax.py file) so I can see what string came after the "ajax/". I'm not sure how to do this or if this would be a good idea to do this....Could anyone offer some advice? thanks :)
You could set up a dispatcher view for handling these. For example, in your urls.py:
(r'^ajax/do_(?P<do_token>(\d+))/$', 'do_dispatcher', {}, "di_dispatcher"),
Then, give yourself a view to handle it:
def do_a(request):
pass
def do_b(request):
pass
def do_c(request):
pass
DO_LOOKUP = {
'a' = do_a,
'b' = do_b,
'c' = do_c,
}
def do_dispatch(request, do_token):
do_func = DO_LOOKUP.get(do_token, None)
if do_func is None:
return HttpResponseNotFound("No do could be found for token '%s'!" % do_token)
else:
return do_func(request)

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."