Skip to content

Commit 788dcad

Browse files
authored
Merge pull request #159 from pythonkr/feature/use-pretalx-on-2024
Feat: 2024년 세션은 pretalx를 사용하도록 수정
2 parents 1935863 + 06bbee9 commit 788dcad

File tree

4 files changed

+159
-3
lines changed

4 files changed

+159
-3
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from __future__ import annotations
2+
3+
import logging
4+
import traceback
5+
import typing
6+
import urllib.parse
7+
8+
import requests
9+
from django.conf import settings
10+
11+
from .serializers import PretalxPaginatedSessionSerializer
12+
13+
logger = logging.getLogger(__name__)
14+
15+
RequestMethodType = typing.Literal["GET", "OPTIONS", "HEAD", "POST", "PUT", "PATCH", "DELETE"]
16+
17+
18+
class PretalxException(Exception):
19+
pass
20+
21+
22+
class PretalxClient:
23+
DEFAULT_TIMEOUT = 5
24+
25+
def _request(self, method: RequestMethodType, endpoint: str, *args: tuple, **kwargs: dict) -> requests.Response:
26+
url = urllib.parse.urljoin(settings.PRETALX.API_URL, endpoint)
27+
request_default_headers = {
28+
"Authorization": f"Token {settings.PRETALX.API_KEY}",
29+
"Content-Type": "application/json",
30+
} | kwargs.pop("headers", {})
31+
request_default_kwargs = {
32+
"headers": request_default_headers,
33+
"timeout": self.DEFAULT_TIMEOUT,
34+
} | kwargs
35+
36+
try:
37+
return requests.request(method, url, *args, **request_default_kwargs)
38+
except Exception as e:
39+
logger.error(traceback.format_exception(e))
40+
raise PretalxException("Pretalx API 요청에 실패했습니다.") from e
41+
42+
def retrieve_sessions(self, event_name: str, only_confirmed: bool = True) -> dict:
43+
"""세션 목록 조회"""
44+
endpoint = f"api/events/{event_name}/submissions" + ("?state=confirmed" if only_confirmed else "")
45+
46+
try:
47+
result = self._request("GET", endpoint)
48+
result.raise_for_status()
49+
50+
parsed_result = PretalxPaginatedSessionSerializer(data=result.json())
51+
parsed_result.is_valid(raise_exception=True)
52+
return parsed_result.validated_data
53+
except Exception as e:
54+
raise PretalxException("세션 목록을 가져오지 못했습니다, 잠시 후에 다시 시도해주세요.") from e
55+
56+
57+
pretalx_client = PretalxClient()
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from rest_framework import serializers
2+
3+
4+
class PretalxSpeakerSerializer(serializers.Serializer):
5+
code = serializers.CharField()
6+
name = serializers.CharField()
7+
biography = serializers.CharField()
8+
avatar = serializers.CharField()
9+
10+
11+
class PretalxSlotSerializer(serializers.Serializer):
12+
start = serializers.DateTimeField()
13+
end = serializers.DateTimeField()
14+
room = serializers.CharField()
15+
room_id = serializers.IntegerField()
16+
17+
18+
class PretalxQuestionSerializer(serializers.Serializer):
19+
id = serializers.IntegerField()
20+
question = serializers.DictField()
21+
required = serializers.BooleanField()
22+
target = serializers.CharField()
23+
options = serializers.ListField()
24+
25+
26+
class PretalxAnswerSerializer(serializers.Serializer):
27+
id = serializers.IntegerField()
28+
question = PretalxQuestionSerializer()
29+
answer = serializers.CharField()
30+
answer_file = serializers.CharField()
31+
submission = serializers.CharField()
32+
person = serializers.CharField()
33+
options = serializers.ListField()
34+
35+
36+
class PretalxSessionSerializer(serializers.Serializer):
37+
code = serializers.CharField()
38+
submission_type = serializers.CharField()
39+
submission_type_id = serializers.IntegerField()
40+
state = serializers.CharField()
41+
42+
image = serializers.CharField()
43+
title = serializers.CharField()
44+
abstract = serializers.CharField()
45+
description = serializers.CharField()
46+
notes = serializers.CharField()
47+
internal_notes = serializers.CharField()
48+
content_locale = serializers.CharField()
49+
50+
slot = PretalxSlotSerializer()
51+
duration = serializers.IntegerField()
52+
do_not_record = serializers.BooleanField()
53+
is_featured = serializers.BooleanField()
54+
55+
speakers = PretalxSpeakerSerializer(many=True)
56+
answers = PretalxAnswerSerializer(many=True)
57+
58+
tags = serializers.ListField()
59+
tag_ids = serializers.ListField()
60+
61+
62+
class PretalxPaginatedSessionSerializer(serializers.Serializer):
63+
count = serializers.IntegerField()
64+
next = serializers.CharField()
65+
previous = serializers.CharField()
66+
results = PretalxSessionSerializer(many=True)

pyconkr/settings.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
For the full list of settings and their values, see
1010
https://docs.djangoproject.com/en/4.1/ref/settings/
1111
"""
12-
1312
import os
1413
import pathlib
14+
import types
1515

1616
# Build paths inside the project like this: BASE_DIR / "subdir".
1717
BASE_DIR = pathlib.Path(__file__).resolve().parent.parent
@@ -246,3 +246,12 @@
246246
LOGIN_URL = "/accounts/login/"
247247

248248
AWS_QUERYSTRING_AUTH = False
249+
250+
# External APIs
251+
PRETALX = types.SimpleNamespace(
252+
API_URL=os.getenv("PRETALX_API_URL", "https://pretalx.com"),
253+
API_KEY=os.getenv("PRETALX_API_KEY", ""),
254+
EVENT_NAME={
255+
"2024": os.getenv("PRETALX_EVENT_TITLE_2024", "pyconkr2024"),
256+
},
257+
)

session/viewsets.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from django.conf import settings
2+
from drf_spectacular.utils import OpenApiExample, OpenApiResponse, extend_schema
13
from rest_framework.permissions import IsAuthenticatedOrReadOnly
24
from rest_framework.viewsets import ModelViewSet
35

6+
from pyconkr.external_apis.pretalx.client import pretalx_client
7+
from pyconkr.external_apis.pretalx.serializers import PretalxSessionSerializer
48
from session.models import Session
59
from session.serializers import SessionListSerializer, SessionSerializer
610

@@ -13,8 +17,28 @@ class SessionViewSet(ModelViewSet):
1317
def get_serializer_class(self):
1418
if self.action == "list":
1519
return SessionListSerializer
16-
else:
17-
return SessionSerializer
20+
return SessionSerializer
1821

1922
def get_queryset(self):
2023
return super().get_queryset().filter(category__year=self.request.version)
24+
25+
@extend_schema(
26+
examples={
27+
200: OpenApiResponse(
28+
response=str,
29+
examples=[
30+
OpenApiExample(name="2023년 세션 목록", value=SessionListSerializer(many=True)),
31+
OpenApiExample(name="2024년 이후 세션 목록 (Pretalx)", value=PretalxSessionSerializer(many=True)),
32+
],
33+
),
34+
},
35+
)
36+
def list(self, request, *args, **kwargs):
37+
if request.version == 2023 or request.version not in settings.PRETALX.EVENT_NAME:
38+
return super().list(request, *args, **kwargs)
39+
40+
pretalx_event_name = settings.PRETALX.EVENT_NAME[request.version]
41+
return pretalx_client.retrieve_sessions(
42+
event_name=pretalx_event_name,
43+
only_confirmed=settings.DEBUG,
44+
)["results"]

0 commit comments

Comments
 (0)