Trying to get data from google books API but it is showing the error ' 'method' object is not subscriptable'
I know the “TypeError: ‘method’ object is not subscriptable” error is raised when you use square brackets to call a method inside a class. To solve this error, make sure that you only call methods of a class using round brackets after the name of the method you want to call.
def books(request):
if request.method == "POST":
form = DashboardForm(request.POST)
text = request.POST['text']
url = 'https://www.googleapis.com/books/v1/volumes?q='+text
r = requests.get(url)
answer = r.json
result = []
for i in range(10):
result_dict= {
'title':answer['items'][i]['volumeInfo']['title'], # This line is showing error.
'subtitle': answer['items'][i]['volumeInfo']['title'].get('subtitle'),
'description': answer['items'][i]['volumeInfo']['title'].get('description'),
'count': answer['items'][i]['volumeInfo']['title'].get('pageCount'),
'categories': answer['items'][i]['volumeInfo']['title'].get('categories'),
'rating': answer['items'][i]['volumeInfo']['title'].get('pageRating'),
'thumbnail': answer['items'][i]['volumeInfo']['title'].get('imageLinks'),
'preview': answer['items'][i]['volumeInfo']['title'].get('previewLink')
}
result.append(result_dict)
context={
'form':form,
'results':result,
}
return render(request,'dashboard/books.html',context)
else:
form = DashboardForm()
context = {'form':form}
return render(request,'dashboard/books.html',context)
In line 7, you write:
answer = r.json
But r.json is a method which you should call:
answer = r.json()
Related
Trying to run this code to get the topstories from hacker news is giving me this error 'TypeError: list indices must be integers or slices, not str', the error is generated at
story = data['story']
from multiprocessing import context
from django.shortcuts import render
import requests
# Create your views here.
def index(request):
#make an api call and save response
url = f'https://hacker-news.firebaseio.com/v0/topstories.json'
response = requests.get(url)
data = response.json()
story = data['story']
context = {
'story': story
}
return render(request, 'SyncNews/index.html', context)
What can I do to correct this error as I'm following a video showing a similar project but this error was not seen, I've also tried removing the '' but receive an error 'UnboundLocalError at /
local variable 'story' referenced before assignment'
story = data['story']
Your 'data' is a list of numbers, not a dictionary. Depending on whether you want to have one or more numbers from that list you can do one of such options:
# first number:
def index(request):
...
data = response.json()
story = data[0]
context = {
'story': story
}
return render(request, 'SyncNews/index.html', context)
# list of numbers:
def index(request):
...
data = response.json()
context = {
'story': data
}
return render(request, 'SyncNews/index.html', context)
I have a problem with django-pytest
I'm using, djnago-rest-framework
There is a problem testing the details. As shown in the code below, I entered the same details, detail1, detail2, and detail3 codes. However, only detail1 succeeds and detail2, detail3 indicates that '/api/v1/stats/1/' could not be found. It also occurs when implementing delete. I am curious about the cause and solution of this error.
enter image description here
// tests/test_apis.py
import json
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from stats.models import Stats
class StatsApiTests(APITestCase):
def setUp(self):
Stats.objects.get_or_create(blockshots=1, memo='test1')
Stats.objects.get_or_create(blockshots=2, memo='test2')
self.create_read_url = reverse('api:stats:stats-list')
self.read_update_delete_url = reverse('api:stats:stats-detail', kwargs={'pk': '1'})
def test_detail1(self):
response = self.client.get(self.read_update_delete_url)
data = json.loads(response.content)
content = {
'blockshots': 1,
'memo': 'test1',
}
self.assertEqual(data, content)
def test_detail2(self):
response = self.client.get(self.read_update_delete_url)
data = json.loads(response.content)
content = {
'blockshots': 1,
'memo': 'test1',
}
self.assertEqual(data, content)
def test_detail3(self):
response = self.client.get(self.read_update_delete_url)
data = json.loads(response.content)
content = {
'blockshots': 1,
'memo': 'test1',
}
self.assertEqual(data, content)
def test_list(self):
response = self.client.get(self.create_read_url)
self.assertContains(response, 'test1')
self.assertContains(response, 'test2')
Its hard to know what your actual implementation for read_update_delete_url, hence I assume it is looking up the resource by primary key. In that case, you can simply add the primary key in the url like this:
stat_one, _ = Stats.objects.get_or_create(blockshots=1, memo='test1')
stat_two, _ = Stats.objects.get_or_create(blockshots=2, memo='test2')
self.read_update_delete_url = reverse('api:stats:stats-detail', kwargs={'pk': stat_one.pk})
Basically, get_or_create returns the object and the state of the object (created or not). You can use the object's id as the parameter of reverse function.
When I run my test, which is the following:
def test_match_data_while_updating(self):
match_updated_data = {
'id': 1,
'status': 'not_started',
}
match = Match.objects.first()
# TST N.1 : status not_started
# -------
match.status = 'not_started'
request = self.__class__.factory.put('', match_updated_data, format='json')
add_authentication_to_request(request, is_staff=True)
response = update_match_video(request)
self.assertEqual(Match.objects.first().status,'live')
I get the Error that says:
print('request data get match: ',request.data.get('match').get('id'))
AttributeError: 'NoneType' object has no attribute 'get'
Here is the function I'm testing:
def update_match_video(request):
print('request data get match: ',request.data.get('match').get('id'))
if not request.data.get('match').get('id'):
return JsonResponse({}, status=status.HTTP_400_BAD_REQUEST)
try:
match_id = valid_data_or_error(request.data, method='PUT')['match_data']['id']
match = Match.objects.get(id = match_id)
db_match_status = match.status
if db_match_status == 'live':
valid_data_or_error(request.data, method='PUT')['match_data']['status'] = 'live'
else:
if db_match_status == 'closed':
valid_data_or_error(request.data, method='PUT')['match_data']['status'] = 'closed'
except Match.DoesNotExist:
print('Match does not exist')
I will appreciate some help please!
Well, request.data is None:
One way to be certain to hit a function that takes a request argument is to use Django's test client and be certain to PT the value that you are expecting:
from django.test import Client
from django.test import TestCase
... other import as needed
class TestMyFunc(TestCase):
def setUp(self):
self.client = Client()
def test_match_data_while_updating(self):
match_updated_data = {
'id': 1,
'status': 'not_started',
}
match = Match.objects.first()
# TST N.1 : status not_started
# -------
match.status = 'not_started'
response = self.client.put( .... ) ## JSON of put data -- make certain to PUT "{ .., match: "something!", ..}
self.assertEqual(response.status_code, 200)
... other assertions
Now, this creates a test database (and ought to have no side effects (unit test, not integration test)) and can be repeated reliably.
To get django to run this test put it in a directory called tests under the main project directory (adjacent to views, models, etc) and do python manage.py run tests
Hope that helps
My code looks like this :
def rssfeeds(request):
reqdata = request.GET['url']
if reqdata == '':
d = "https://github.com/rudrasingh99.private.atom?token=MYPRIVATETOKEN"
data = []
for post in d.entries:
data.append(post.title)
my_context = {
"my_list" : data,
}
else:
d = feedparser.parse(reqdata)
data = []
for post in d.entries:
data.append(post.title)
my_context = {
"my_list" : data,
}
return render(request,"base.html",my_context)
def home_view(request):
return render(request,"index.html",{})
while whenever i try with empty url parameter it gives me 500 error.
Thanks in advance
It gives you a 500 error because the request.GET is a dictionary. It's really a KeyError under the hood; set DEBUG=True to find this.
Use .get to get terms with default values and handle appropriately.
reqdata = request.GET.get('url', 'mydefaultvalue')
If url is required for the page to load properly, maybe consider returning a human readable error?
reqdata = request.GET.get('url', '')
if reqdata == '':
return HttpResponse("Specify a url!")
I have these methods:
def get_all_from_database():
urls = Url.objects.all()
ips = Ip.objects.all()
context = {
'urls': serializers.serialize('json', urls),
'ip': serializers.serialize('json', ips)
}
return context
and the method that sends data to using ajax:
def send_results(request):
if request.is_ajax():
address = request.POST.get('url')
process_data(address, email_to, email_from)
context = get_all_from_database()
return HttpResponse(json.dumps(context), content_type='application/json')
But this raises error : INTERNAL SERVER ERROR 500 'dict' object has no attribute '_meta'.
Wheres the mistake, and how to correct it ?
You cant use serializers.serialize method with dict list that you got from values call:
urls = Url.objects.all().values('address', 'cnt')
Use default queryset:
urls = Url.objects.all()
ips = Ip.objects.all()
In you example context['urls'] value already in json format, and you cant use json.dumps() for json data.
You can use this example:
json.dumps({
'urls': Urls.objects.all().values_list('address', 'cnt'),
'ips': Ip.objects.all().values_list('address', 'cnt')
}), 'json')
urls = Url.objects.all().values('address', 'cnt')
ips = Ip.objects.all().values('address', 'cnt')
The above lines returns dict objects, try:
urls = Url.objects.all().values('address', 'cnt').values_list()
ips = Ip.objects.all().values('address', 'cnt').values_list()
Then you will have urls as a list containing the tuples:
[(address_1, cnt_1), (address_2, cnt_2), ...]
see: QuerySet API reference
I think it should be :
res=json.dumps({
'urls': list(Urls.objects.all().values_list('address', 'cnt')),
'ips': list(Ip.objects.all().values_list('address', 'cnt'))
}), 'json')
return HttpResponse(res,content_type="application/json")