
์ฃผ์! ์์๋ ํ์ฌ(2023๋ ) REST API๋ฅผ ๋ชจ๋ฆ ๋๋ค.. ๋์ค์ ๋ฐฐ์ธ๊ฒ์๐
๋ํ๊ฐ์ ๊ด๋ จ ํ๋ก๊ทธ๋จ์ ๋ง๋ค๊ธฐ ์ํด api(canvas LMS api)๋ฅผ ํ์ด์ฌ์ผ๋ก ๋ค๋ฃจ๋ canvasapi๋ฅผ ๋ค๋ฃจ๋ค๊ฐ ํ์ด๋์จ ๋จ์ด์ด๋ค.
์๋๋ canvasapi docs์ค ์ผ๋ถ์ด๋ค.

์ฌ๊ธฐ์ get_courses()๋ ํ์ฌ ๊ณ์ ์ด ์๊ฐ์ค์ธ ๊ฐ์ข (๊ด๋ฆฌ์๋ผ๋ฉด ์ด์์ค์ธ ๊ฐ์ข)๋ฅผ ๋ชจ๋ ๊ฐ์ ธ์ค๋ ํจ์์ด๋ค. ๋ชจ๋ ๊ฐ์ ธ์ค๋ฏ์ด ์ผ๋ฐ์ ์ธ ํ์ด์ฌ ๊ธฐ๋ฅ์ฒ๋ผ list์ ํํ๋ก ๊ฐ์ ธ์ค๋ ์ค ์์์ง๋ง, canvasapi.paginated_list.PaginatedList ํ์์ ๋ฐ๋ฅธ๋ค. ์ผ๋ฐ์ ์ธ list ํ์๊ณผ ๋น์ทํ ํ์์ด๋ผ๊ณ ์๊ฐํ์ง๋ง, ๋ญ๊ฐ ์๋ ๋ฐฉ์์ด ๋ค๋ฅธ ๋๋์ด์๋ค.
์๋ฅผ ๋ค๋ฉด
import canvasapi
canvas = canvasapi.Canvas('api_url', 'token')
canvas.get_courses()[0] # ์๋ํ๋ค
canvas.get_courses()[:] # ์๋ํ์ง ์๋๋ค
# ๋ชจ๋ ๊ฐ์ ๊ฐ์ ธ์ค๋ ค๋ฉด ์ด๋ ๊ฒ ํด์ผ ํ๋ค.
courses: list = []
for course in canvas.get_courses():
courses.append(course)
iterator ํน์ฑ์ ๊ฐ์ก์ง๋ง ์ฌ๋ผ์ด์ฑ์ ์๋๊ณ , print๋ฅผ ํด๋ ๊ฐ์ฒด ๊ฐ๋ง ๋ด๋ฑ๋๋ค. ์ฌ์ง์ด ์ธ๋ฑ์ค ๊ฐ์ ํฌ๊ฒ ํด๋์ผ๋ฉด ํจ์๊ฐ ๋ค์ ๋๋ฆฌ๊ฒ ์๋ํ๊ธฐ๋ ํ๋ค.
canvasapi/canvasapi/paginated_list.py

์ผ๋จ self._elements์ ์๋ ์์๋ค์ ๋ฐํํ ๋ค์, ๋ง์ง๋ง์ ๋๋ฌ ํ์ ๋ ๊น์ง self._grow()๋ฅผ ๋ถ๋ฌ์์ ๊ทธ ์์๋ค์ ๋ฐํํ๋ค
def _grow(self):
new_elements = self._get_next_page()
self._elements += new_elements
return new_elements
def _get_next_page(self):
response = self._requester.request(
self._request_method,
self._next_url,
_url=self._url_override,
**self._next_params,
)
data = response.json()
...
return content
์ถ์ธกํ๊ฒ ๋ง์๋ค. PaginatedList ๋ _grow() ์คํ์ _get_next_page() ๋ฅผ ์คํํ๋ฉด์ ๊ทธ ๋ฐ์ดํฐ๋ฅผ self._elements์ ๋ฃ์ ๋ค์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ค. ๊ทธ๋ฆฌ๊ณ _get_next_page() ์๋ request๋ฅผ ๋ฐ๋ ํจ์๊ฐ ์๋ค.
๋ฐ๋ผ์ ์ด PaginatedList ๋ for๋ฌธ์ ์ง์ด๋ฃ๊ณ ์คํ์ํค๋ฉด, ๊ธฐ์กด์ ๋ฏธ๋ฆฌ ๋ถ๋ฌ์๋ ๋ฐ์ดํฐ๋ค์ ๊ฐ์ ธ์ค๊ณ , ๊ทธ ํ ํ๊ฐ์ฉ ๋์ด๊ฐ ๋๋ง๋ค api ์์ฒญ์ ๋ณด๋ด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์์ผ๋ก ๋์ด์๋ค.
๊ฐ์ธ์ ์ผ๋ก (์ด์ฒํผ ๋ชจ๋ ๋ฐ์ดํฐ ์ฌ์ฉํ๋๋ฐ) list๋ก ๋ณํํ๋ ๊ธฐ๋ฅ๋ ๋ง๋ค์ด ์ฃผ์์ผ๋ฉด ํ์ง๋ง, ๊ทธ๋ ๊ธฐ์ ์ฌ๋๋ค์ด ๋ง์ด ์ฐ์ง ์์์ ๋ง๋ค์ง ์์ ๊ฒ ๊ฐ๋ค.
์ผ๋จ PaginatedList๊ฐ ์ด๋์ ๋์จ ๋จ์ด์ธ์ง ๊ฒ์ํด๋ณด์

์ด ๋ฐ์๋ ๋ด๊ฐ ๋ค๋ฃจ๊ณ ์์๋ canvasapi api ๋ฌธ์๊ฐ ๊ทธ๋๋ก ๋์จ๋ค ์๋ฌด๋๋ ์ ์ฐ์ง ์๋ ํ์์ธ๊ฐ ๋ณด๋ค
์๋ง์กด ๋งํฌ์ PyGithub(github api๋ฅผ ํ์ด์ฌ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์๊ฒ ๋ง๋๋ ํจํค์ง)๊ฐ ๋์ ๋๋ ํตํด๋๊ณ ์ฉ์ด๋ฅผ ๊ฒ์ํด๋ณด์.
Pagination : ํ์ด์ง์ด๋ผ๊ณ ๋ ํ๋ ํ์ด์ง ๋งค๊น์ ๋ฌธ์๋ฅผ ์ ์ ํ์ด์ง ๋๋ ์ธ์๋ ํ์ด์ง์ ๊ฐ์ ๊ฐ๋ณ ํ์ด์ง๋ก ๋๋๋ ํ๋ก์ธ์ค์ ๋๋ค.
ํ์ด์ง ํ์..์ด๋ผ๊ณ ํ๋ ์์๋๋ก ์ฝ์ด์ค๋๊ฑด๊ฐ? ์ถ๋ค.
์ผ๋จ ๋งํฌ์์ ์๋ง์กดdocs ๊ธ์ java dynamodDB์ชฝ์์ ์ฌ์ฉํ๋ ์ ๋ณด์ธ๊ฒ ๊ฐ๋ค.

์๊ด์ด ์์ด๋ณด์ด์ง๋ง, Iterable<T>, Collection<T>, List<T> ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
PyGithub์ PaginatedList.py๋ ๋ง์ฐฌ๊ฐ์ง์ด๋ค


์ด๋ api์๋ ๋ค๋ฅด๊ฒ ์ฌ๋ผ์ด์ฑ์ ์ง์ํ๋ค ๊ทธ๋ฅ api๊ฐ ์ง์์ํ๋๊ฑฐ์๋ค..
์๋ฌดํผ __iter__ ๊ณผ์ ์ ์ดํด๋ณด์. ์ฌ๊ธฐ์๋ self.__grow๋ฅผ ํตํด ์๋ก์ด ์์๋ฅผ ๊ฐ์ ธ์จ๋ค.
def _grow(self) -> List[T]:
newElements = self._fetchNextPage()
self.__elements += newElements
return newElements
def _fetchNextPage(self) -> List[T]:
raise NotImplementedError
PaginatedListBase์ฌ์ ์๋์ ์ผ๋ก ์๋ฌ๋ฅผ ์ผ์ผํค๋ ๊ฒ ๊ฐ๋ค(๋ ๊ทธ๋ฅ pass ๋ก ๋ฐฉ์นํด๋จ์๋๋ฐ ์ข์๊ฑฐ ์๊ณ ๊ฐ๋๋ค)
class PaginatedList(PaginatedListBase[T]):
# (์๋ต)
def _fetchNextPage(self) -> List[T]:
headers, data = self.__requester.requestJsonAndCheck(
"GET", self.__nextUrl, parameters=self.__nextParams, headers=self.__headers
)
data = data if data else []
return self._getPage(data, headers)
์ฌ๊ธฐ์๋ ์ธ๋ฑ์ค๊ฐ ๋์ด๋ ๋๋ง๋ค self.__requester.requestJsonAndCheck๋ฅผ ํตํด ์๋ก ์์ฒญ์ ๋ฐ์์จ๋ค๋ ๊ฒ์ ์ ์ ์๋ค.
๊ทธ๋ฅ ์๋ ๊ธฐ๋ฅ์ด๊ตฌ๋.. ํ๋ฉด์ ๋ค์ฌ๋ค ๋ณด์์ง๋ง ์๊ฐ๋ณด๋ค ์ป์ ์ ์ด ์๋ค. ๋ฐ๋ก (๋ฌผ๋ก PyGithub) ์ฝ๋๊ฐ ์์ฒญ ๊น๋ํ๊ณ ์ ๊ตฌ์กฐ๊ฐ ์ ์ง์ฌ์ ธ์๋ค๋ ๊ฒ ์ด๋ค..! ๋์ค์ ์ฐธ๊ณ ํด์ผ๊ฒ ๋ค.