I'm having trouble getting the JSON for function based views in django. I have the below code. I basically would like the function to return either json or an html page based on the user request.
#api_view(['GET'])
#renderer_classes((JSONRenderer,TemplateHTMLRenderer,BrowsableAPIRenderer))
def meld_live_orders(request):
if request.method =='GET':
current_orders = Meld_Sales.objects.values_list('TicketNo',flat=True).distinct()
prev_orders = Meld_Order.objects.values_list('TicketNo',flat =True).distinct()
live_orders = live_order_generator(current_orders,prev_orders)
return render(request,'live_orders.html',{'live_orders':live_orders})
When i go to the url - http://localhost:8000/live-orders.json
I'm getting an error which states the below -meld_live_orders() got an unexpected keyword argument 'format'
Is this because i need to include the serializer class somewhere the same way in CBVs? Doesnt the #API_VIEW serialize the response?
i tried including format = '' in the function argument. but the problem is that it still renders html when i want it to render json.
You need to make some changes to your code.
Firstly, you need to use format_suffix_patterns in your urls if you have not defined it. This will allow us to use filename extensions on URLs thereby providing an endpoint for a given media type.
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
...
]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) # allow us to use '.json' and '.html' at the end of the url
Secondly. your view does not have a format parameter in the definition.
When using format_suffix_patterns, you must make sure to add the
'format' keyword argument to the corresponding views.
#api_view(['GET'])
#renderer_classes((JSONRenderer,TemplateHTMLRenderer,BrowsableAPIRenderer))
def meld_live_orders(request, format=None): # add a 'format' parameter
...
Thirdly, you need to return a DRF response and not a Django response which you are returning at the end of the view.
You must have match a format parameter in the url pattern, but in the view function there is not an argument named format. Change the view definition into:
def meld_live_orders(request, format = ""):
Related
Is it possible to pass context through the reverse function in Django in some way like reverse('foo', context={'bar':'baz'})? Or is there a better workaround?
As already described by Sir WillemVanOnsem in the above comment.
You can't provide context in reverse as it only produces a string: a path, eventually it goes to view.
reverse() can only take args and kwargs, see Reversing namespaced URLs for more detail.
Reverse generates an URL. The URL can parse or supply extra context. In urls.py,
path( 'action/<str:context>/', MyView.as_view(), name='foo' )
then
reverse('app:foo', kwargs={'context':'bar:baz+quux:help'} )
will generate the URL ending
.../appname/action/bar:baz+quux:help
and your view will parse context:
context = self.kwargs.get( context, '')
context_dir = {}
for kv in context.split('+'):
keyval = kv.split(':')
context_dir[ keyval[0].strip() ] = keyval[1].strip()
or something like this, ending with context_dir as {'bar':'baz', 'quux':'help'}
Alternatively you can append a querystring to the URL returned by reverse and retrieve that in the view you redirect to via request.GET
url = reverse('foo') + '?bar=baz&quux=help'
redirect, and then in that view request.GET.get('bar') will return "baz" etc.
Finally you can stuff an almost arbitrarily complex context into the user's session (which gets stored either as a cookie in his browser, or an object in your database). This is the most general but also the most complex. See the doc for using Django sessions
I've recently started with Django and I'm unable to understand how to route the URL based on the value of a 'action' parameter which'll be passed along with some other parameters in the URL. So the goal is to filer out the value of the 'action' parameter and routing the url to seperate views accordingly.
For example..
If the URL is:-
/api/?param1=value¶m2=value&action=status
it should be routed to the status view
if it's
/api/?param1=value&action=add¶m2=value
be routed to the add view
and so on no matter the value and position of the other parameters.
I'm unable to understand how to route the URL based on the value of a 'action' parameter which'll be passed along with some other parameters in the URL.
The part after the question mark (?) is called the querystring [wiki]. It is not part of the path, hence the Django routing mechanism does not take it into account. You can access these parameters with request.GET [Django-doc], which is a QueryDict object [Django-doc]. A QueryDict is a dictionary-like object, but a key can map to multiple values.
You will need to perform the correct action in the view itself. So you can implement a path like:
# myapp/urls.py
from django.urls import path
from myapp import views
urlpatterns = [
path('api/', views.myapi, name='api')
]
In the view you can then specify how to act accordingly:
# myapp/views.py
def myapi(request):
if request.GET.get('action') == 'add':
# …
pass
if request.GET.get('action') == 'status':
# …
pass
# …
However in Django web applications, often the action is part of the path. So one makes urls that look for example like:
api/model1/
api/model1/pk
api/model1/add
I'm trying to retrieve a url parameter as part of a simple query within Django but calling kwargs from within the view.py seems to return an empty value (e.g. self.kwargs[name] returns a blank/empty value), it seems Im not picking up the 'name' parameter from the url?
Im pretty new to Django so expect I'm doing something dumb?
I'm using the following url:
myIpAddress:8000/contacts/search_name/?name=gordon
my code:
URL pattern - works fine.
urlpatterns = [
url(r'^contacts/$', ContactList.as_view()),
url(r'^contacts/search_name/(?P<name>\w{0,50})$', ContactDetail.as_view()),
]
view:
class ContactDetail(generics.ListAPIView):
serializer_class = ContactSerializer
def get_queryset(self):
return Contact.objects.filter(name=self.kwargs['name'])
Not sure if it's the best way but I managed to grab the URL parameter using:
self.request.GET.get('name')
This returns the parameter supplied within the url.
I am trying to make a query system for my website, i think the best way and the most compact would be to assign search variable using url pattern.
So for example, i want to search objects of model User:
User sends HttpRequest to following url:
https://127.0.0.1/search/q="admin"
Now HttpRequest is also sent to search view, we somehow get q variable data.
def search(request):
for query in User.objects.all():
if q in query: # < We somehow need to get data of 'q'.
return HttpResponse(q)
Since i have admin in User.objects.all(), this should return HttpResponse of 'admin'.
How can this url pattern be made? So i can assign q variable from the url and then send it to system to find it?
I have problems with this URL:
https://127.0.0.1/search/q="admin"
There is no ? in the URL, so there is no query string, it's all part of the "path". Using characters like = and " in there will confuse a lot of things, if it works at all.
Either just do
https://127.0.0.1/search/admin
With an URL pattern like r'^search/(?P<querystring>.+)$', or
https://127.0.0.1/search/?q=admin
In this case the query string will be in request.GET['q']; it's also possible to use Django forms to process query parameters (e.g. for validating them).
You can capture named strings from URLs like this:
urls.py:
urlpatterns = [
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]
views.py:
def page(request, num="1"):
I am trying to write something elegant where I am not relying on Request object in my code. All the examples are using:
(r'^hello/(?P.*)$', 'foobar.views.hello')
but it doesn't seem like you can post to a URL like that very easily with a form. Is there a way to make that URL respond to ..../hello?name=smith
Absolutely. If your url is mapped to a function, in this case foobar.views.hello, then that function might look like this for a GET request:
def hello(request):
if request.method == "GET":
name_detail = request.GET.get("name", None)
if name_detail:
# got details
else:
# error handling if required.
Data in encoded forms, i.e. POST parameters, is available if you HTTP POST from request.POST.
You can also construct these yourself if you want, say, query parameters on a POST request. Just do this:
PARAMS = dict()
raw_qs = request.META.get('QUERY_STRING', '') # this will be the raw query string
if raw_qs:
for line in raw_qs.split("&"):
key,arg = line.split("=")
PARAMS[key] = arg
And likewise for form-encoded parameters in non POST requests, do this:
FORM_PARAMS = QueryDict(request.raw_post_data)
However, if you're trying to use forms with Django, you should definitely look at django.forms. The whole forms library will just generally make your life easier; I've never written a html form by hand using Django because this part of Django takes all the work out of it. As a quick summary, you do this:
forms.py:
class FooForm(forms.Form):
name = fields.CharField(max_length=200)
# other properties
or even this:
class FooForm(forms.ModelForm):
class Meta:
model = model_name
Then in your request, you can pass a form out to the template:
def pagewithforminit(request):
myform = FooForm()
return render_to_response('sometemplate.html', {'nameintemplate': myform},
context_instance=RequestContext(request))
And in the view that receives it:
def pagepostingto(request):
myform = FooForm(request.POST)
if myform.is_valid(): # check the fields for you:
# do something with results. if a model form, this:
myform.save()
# creates a model for you.
See also model forms. In short, I strongly recommend django.forms.
You can't catch GET parameters in a URL pattern. As you can see in django.core.handlers.base.BaseHandler.get_response, only the part of the URL that ends up in request.path_info is used to resolve an URL:
callback, callback_args, callback_kwargs = resolver.resolve(
request.path_info)
request.path_info does not contain the GET parameters. For handling those, see Ninefingers answer.