im implementing api requests
to my tkinter app. At the Gui Class init
there is one api request
running that works without problems. But when im calling a function
inside the class
that is running the same api request
im getting back an error
.
I'm not quite sure if it is the API
or maybe my class structure
.
My folder structure looks like this
Project Folder/
api/
__init__.py
api.py
gui/
__init__.py
gui.py
main.py
The main.py
holds the Gui Class
with the mainloop
.
from gui.gui import Gui
if __name__ == '__main__':
app = Gui()
app.mainloop()
The GUI class
contains the tkinter app and is inherited from customtkinter.CTk
. Simplified it looks like that
import logging
import PIL.Image
from tkinter import *
import tkinter.messagebox
import customtkinter
from api.api import WikiApi
class Gui(customtkinter.CTk):
def __init__(self):
super().__init__()
# API
self.api = WikiApi()
self.book_list = self.api.get_all_books_from_shelv()['books'] # Fetching all book names from api
# API Output looks like this
'''
{
'books': [{
'id': 37,
'name': 'book-1',
'slug': 'book-1',
'description': '',
'created_at': '2023-04-11T09:16:19.000000Z',
'updated_at': '2023-04-14T08:40:49.000000Z',
'created_by': 16,
'updated_by': 4,
'owned_by': 16
}, {
'id': 38,
'name': 'book-2',
'slug': 'book-2',
'description': '',
'created_at': '2023-04-13T07:07:23.000000Z',
'updated_at': '2023-04-13T07:07:23.000000Z',
'created_by': 16,
'updated_by': 16,
'owned_by': 16
}
]
}
'''
# logger
# screen constants
# root window attributes & widgets
# refresh button that calls self.refresh_book_list
def refresh_book_list(self):
self.book_list.clear()
self.book_list = [book['name'] for book in self.api.get_all_books_from_shelv()['books']]
# API response from function
'''
{
'error': {
'code': 403,
'message': 'The owner of the used API token does not have permission to make API calls'
}
}
'''
The api.py
contains the class WikiApi
and simplified looks like this
import requests
import logging
import json
class WikiApi:
def __init__(self):
self.TOKEN_ID = 'abcdef123'
self.TOKEN_SECRET = 'password'
self.HEADER = {
"Authorization": f"Token {self.TOKEN_ID}:{self.TOKEN_SECRET}",
"Accept": "application/vnd.api+json"
}
self.session = requests.session()
self.session.headers = self.HEADER
def _get(self, url):
response = self.session.get(url)
return response.json()
def get_all_books_from_shelv(self):
url = f'url to api endpoint'
response = self._get(url)
return response
It looks like (and you've seemingly confirmed) that the issue has to do with state retained in the requests.session()
between the two API calls.
To get more precise details about precisely why involves diving into the requests.session()
implementation or docs for details.
IIRC, requests
has an extra-verbose way of "logging prepared requests" that can help you at this point.