Query json http response from browser - python

I have a view written in Django which returns JSON response like:
[{"pk": 3222, "model": "test.test", "fields": {"f1:f1, f3:f2"}}......etc]
The URL that returns this view is: 127.0.0.1:8000/someview/modelname/all
However when I hit this on a browser 127.0.0.1:8000/someview/modelname/all?pk=3222
I do not get the filtered result. How do I achieve this? Or is my understanding of query in a URL wrong.
UPDATE:
In my view:
obj = SomeModel.objects.all()
return HttpResponse(serializers.serialize('json', [obj,]))

This is because you're not doing any filtering in your code at all. Your first line says "give me all the SomeModel objects" and your second line says "here's an HTTP response of all the SomeModel objects as JSON."
Assuming you're not using class-based views, you can do something like this:
from django.shortcuts import get_object_or_404
def SomeView(request):
obj = SomeModel.objects.all()
if request.GET.get('pk') is not None:
obj = get_object_or_404(SomeModel, pk=request.GET.get('pk'))
return HttpResponse(serializers.serialize('json', obj), content_type="application/json")

You only must GET the pk argument and with the pk you can GET the record:
if request.GET['pk']:
p_k = int(request.GET['pk'])
obj = Somemodel.objects.get(pk=p_k)
else:
obj = SomeModel.objects.all()

Related

Can we send the HttpResponse of django `render()` in a python dictionary?

What my use case is I need whole render() data into a dictionary which will be having other key values too and finally I can return it as a normal Response.
Let suppose my code is:
from django.shortcuts import render
def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')
Now what we are doing here is: render is basically returning a HttpResponse which we are returning.
What I need is:
Save the return response in a variable
x = render(request, 'myapp/index.html', {
'foo': 'bar',
}, content_type='application/xhtml+xml')
Then can we save it in a dictionary to return as a Response? Like this
y = {}
y = {name: 'testing', render_response: x}
return y
You cant return a plain dictionary from a view, it should return a HttpResponse object. You can return a JsonResponse from your view. Like #Daniel mentioned in comments, use render_to_string to get response in string format.
from django.template.loader import render_to_string
from django.http import JsonResponse
def my_view(request):
# View code here...
response = render_to_string('myapp/index.html', {'foo': 'bar'}, request=request)
context = {'name': 'testing', 'render_response': response}
return JsonResponse(context)
To answer your question: yes, you can. Your code, which I am rewriting here, is absolutely valid:
from django.shortcuts import render
def my_view(request):
x = render(
request,
'myapp/index.html',
{'foo': 'bar'},
content_type='application/xhtml+xml'
)
y = {name: 'testing', render_response: x}
return y
That said, you have to keep in mind that my_view is no longer a valid Django view. It is just a function that takes a request object and returns a dictionary (with an HttpResponse as one of its values).
For that reason, you will not be able to use this function in places where view functions are expected, such as in urlpatterns. A possible use of this function would be within a valid view function (which retrieves the returned HttpResponse object and returns it directly).

Django JsonRequest in generic view always returns a string

(using Django2.0)
This is my first time trying to collaborate with a frond-end developer and I am trying to serialize a Django model from a generic ListView. Even though I manage to send a JsonResponse with my objects as json, they are always a string:
"[{\"model\": \"questions.question\", \"pk\": 9535, \"fields\": {\"created\": \"2018-04-14T17:02:38.559Z\", \"modified\": \"2018-04-14T18:04:14.264Z\", \"question\": \"TEST\", \"category\": \"Rules\", \"event\": \"Beyonce\", \"answer\": \"aergaergaergaer\", \"verified\": true, \"verified_by\": [\"someotheruser\"], \"count\": 0, \"user_created\": [\"someuser\"]}}]"
the way the front-end developer solved this issue is by calling a JSON.parse(). (see: https://www.w3schools.com/js/js_json_parse.asp).
Is this the correct way to do it or should I return the objects without a string?
If I am wrong and there is a way to do this without the strings here is my view and url:
views.py:
from events.models import Event
from django.core import serializers
from django.http import JsonResponse
class EventView(LoginRequiredMixin, ListView):
login_url = '/accounts/login/'
model = Question
template_name = 'faq/faq.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
events_list = Event.objects.all()
context['events_list'] = events_list
return context
def get_queryset(self):
event = Event.objects.get(event=self.kwargs['event'])
queryset = Question.objects.filter(event=event)
return queryset
def get(self, request, *args, **kwargs):
queryset = self.get_queryset()
data = serializers.serialize("json", queryset, use_natural_foreign_keys=True)
return JsonResponse(data, status=200, safe=False)
urls.py
urlpatterns += [
path('<str:event>/', EventView.as_view(), name='event'),
]
What I also tried:
def EventRequest(request, **kwargs):
event = Event.objects.get(event=kwargs['event'])
queryset = Question.objects.filter(event=event)
data = serializers.serialize("json", queryset, use_natural_foreign_keys=True)
dump = json.dumps(data)
return HttpResponse(dump, content_type='application/json')
and:
def EventRequest(request, **kwargs):
event = Event.objects.get(event=kwargs['event'])
queryset = Question.objects.filter(event=event)
data = serializers.serialize("json", queryset, use_natural_foreign_keys=True)
return JsonResponse(data, status=200, safe=False)
Once again this could be absolutely correct and the front-end developer should just do a JSON.parse(). Please let me know, thanks!
This is normal. JSON is a string notation. It is just a format to represent JavaScript objects and arrays (Python dicts and lists) as a string.
In the frontend you'll have to use JSON.parse() to convert it into a JavaScript array (list) or object (dict).
This also holds true when you send JSON from frontend to backend. You use JSON.stringify() to covert the JS object to string. Then in the backend you convert that string to a Python object using json.loads().

How to return data from an API in Django?

Im trying to learn how to use APIs in Django and I want to return some simple data from one within a web page in html. The API is Mozscape and when running it in a terminal one can obtain the score of a website out of 100 like so:
from mozscape import Mozscape
client = Mozscape(
'api_user_id',
'secret_key')
url = 'http://www.google.com'
get_da = client.urlMetrics(url, cols=68719476736)
print(get_da)
and this prints the following
{u'pda': 100}
the '100' is all I want there. I want a user to enter a url into a form in a page in Django and to get that score int back so I have made the following models, views and form
class DomainAuthority(models.Model):
url = models.URLField(max_length=300)
def __str__(self):
return self.url
class Meta:
verbose_name = 'Domain'
verbose_name_plural = 'Domains'
views.py
def DomainAuthorityView(request):
form = DomainAuthorityForm(request.POST or None)
if form.is_valid():
new_domain = form.save(commit=False)
new_domain.save()
return render(request, 'domain_authority.html', {'form': form})
forms.py
class DomainAuthorityForm(forms.ModelForm):
class Meta:
model = DomainAuthority
fields = ['url']
so I have the form working and when a url is entered in the html form its saved in the admin backend but what I dont know how to do now is how to pass that url into the Mozscape API so that I can get the score back.
I took a look at the Django rest framework and installed it and followed some quick tutorial videos on Youtube and other places but in those examples they were taking saved Django objects such as blog posts and returning them as JSON data which is not what I want to do.
I tried import the API into the views file and then adding this line into then view
get_da = client.urlMetrics(new_domain, cols=68719476736)
but then I get this error after entering the url into the form in the web page
<DomainAuthority: https://www.google.com> is not JSON serializable
what do I need to do here to pass the user inputted urls to the API and return the correct response in a web page?
thanks
EDIT - UPDATED VIEW as of 19th Aug
def DomainAuthorityView(request):
form = DomainAuthorityForm(request.POST or None)
if form.is_valid():
new_domain = form.save(commit=False)
new_domain.save()
response = requests.get(new_domain.url, cols=68719476736)
#response = requests.get(client.urlMetrics(new_domain.url, cols=68719476736))
json_response = response.json()
score = json_response['pda']
return render(request, 'domain_authority_checked.html', {'score': score})
else:
return render(request, 'domain_authority.html', {'form': form})
so now it should redirect after successful form completion with url and the url is passed to the API to get the score and the redirects to 'domain_authority_checked.html' with just this
{{ score }}
so I have two outcomes here, if I pass in 'client.urlMetrics' into response I can load the 'domain_authority.html' but after a url his input into the form an error page returns with this
InvalidSchema at /domainauthority/
No connection adapters were found for '{'pda': 100}'
if I dont pass 'client.urlMetrics' to response then Django doesn't know what 'cols' is and returns this
TypeError at /domainauthority/
request() got an unexpected keyword argument 'cols'
I suggest this approach:
import requests
response = requests.get(url)
json_response = response.json()
score = json_response['key_name']
You can then simply render a template, add the score to the template context and display the value using {{ }}.
You may also want to define a rest_framework serializer (otherwise you don't need django_rest_framework) and verify the response against this serializer in order to ensure that you've received what you expected:
serializer = MySerializer(data=json_response)
if serializer.is_valid():
score = json_response['key_name']
You can use:
return HttpResponse(json.dumps(data), content_type='application/json')
instead of render the form. Only you need to import json in the header and create an empty dict named "data".

tasty pie - Return JSON with non ORM object

I am new with tasty pie and I am trying to simply return a json structure from my API.
I have the following class:
class CaseResource(Resource):
class Meta:
authentication = SessionAuthentication()
resource_name = 'case'
allowed_methods = ['get']
def obj_get_list(self, request, **kwargs):
case = request.GET.get('q')
if case:
mycase = connect_and_retrieve_data(request, q)
return self.create_response(request, {'mycase': mycase})
connect_and_retrieve_data is a method that is returning a json_dump for a non ORM object.
When I am sending the GET request in AJAX, I got the following response:
NotImplementedError at /mydashboard/api/v1/case/
No exception message supplied
The API pointed me to "Using Tastypie With Non-ORM Data Sources", though I was hoping for something less heavy handed.
I guess that I have to overwrite all the methods:
detail_uri_kwargs
get_object_list
obj_get_list
obj_get
obj_create
obj_update
obj_delete_list
obj_delete
rollback
but this looks quite heavy. Is there an other way to do this or using a different method?
Thank you in advance for your help,
For one single request you could make none RESTful endpoint. This would be not right if you have decided for some reason that your whole service is going to be 100% RESTful.
But, if you are looking for something less heavily try standard Django view:
import json
from django.http import (HttpResponse,
HttpResponseNotAllowed, HttpResponseForbidden)
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def connect_and_retrieve_data(request):
"""
Docstrings..
"""
if not request.user.is_authenticated():
return HttpResponseForbidden(json.dumps({'message': 'User must be authenticated'}),
content_type='application/json')
if request.method != 'GET':
return HttpResponseNotAllowed(permitted_methods=('GET',))
if request.GET.get('q'):
mycase = connect_and_retrieve_data(request, request.GET.get('q'))
mycase = json.loads(mycase)
return HttpResponse(
json.dumps({'mycase': mycase, 'success': True}),
content_type='application/json')
else:
return HttpResponse(
json.dumps({'message': 'Missing q param', 'success': False}),
content_type='application/json')
Be aware of that your project might be falling out of control soon if you will get too many undocumented and untested endpoints like this in RESTful API. At some point you might consider something else then RESTful. But if it is not more then 10% of all endpoints and nicely described you will be fine.

Displaying JSON data

In django my view.py is
import json
from django.http import HttpResponse
from django.template import Template, Context
from django.shortcuts import render_to_response
def ajax(request):
obj =[dict(a = 1,b = 2)]
jsons=json.dumps(obj)
print jsons
return render_to_response("2.html", {"obj_as_json": jsons})
I want to display value of a and b that are JSON in my template 2.html. Please help me to write the code.
I don't understand the usage of View.
Why do you want to pass JSON object as a context value while Template Rendering ?
The standard is When you do a Ajax request its response should be a JSON response i.e mimetype=application/json.
So, You should render the template normally and Convert the result into JSON and return.
e.g:
def ajax(request):
obj = {
'response': render_to_string("2.html", {"a": 1, "b": 2})
}
return HttpResponse(json.dumps(obj), mimetype='application/json')
OR
you can create a JSONResponse class Similar to HttpResponse to make it generic . e.g.
class JSONResponse(HttpResponse):
"""
JSON response
"""
def __init__(self, content, mimetype='application/json', status=None, content_type=None):
super(JSONResponse, self).__init__(
content=json.dumps(content),
mimetype=mimetype,
status=status,
content_type=content_type,
)
and use like : return JSONResponse(obj)
This has been added by default in django 1.7: https://docs.djangoproject.com/en/1.7/ref/request-response/#jsonresponse-objects

Categories

Resources