강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của colock1232765
colock1232765

câu hỏi đã được viết

Hướng dẫn hoàn chỉnh về phát triển dịch vụ web Python/Django với React

Xác thực JWT

rest_framework_jwt를 임포트할 수 없다는 에러가 발생합니다

Viết

·

1.9K

0

안녕하세요? 강의 잘 듣고 있습니다.
 
강의 11분경 즈음 rest_framework_jwt에러가 발생합니다
가상환경에 알맞게 설치되었는지는 확인했고 / 혹시나 해서 pip uninstall후 다시 install까지 해봣는데도 에러가 발생하네요
찾아보니까 simple-jwt를 써보라는데, 그것도 안되는 것 같았습니다 ㅠ
 
우선 제 settings.py입니다
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.SessionAuthentication',
        # 'rest_framework.authentication.TokenAuthentication',
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ],
 
그리고 이렇게 해둔 상태에서 runserver를 cmd에서 돌리니까
다음과 같은 에러가 cmd에서 발생합니다.
 
(askcompany) C:\Users\user\yb\django_askcompany\askcompany\Scripts\_askcompany8>python manage.py runserver Watching for file changes with StatReloader Performing system checks... Exception in thread django-main-thread: Traceback (most recent call last): File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\settings.py", line 177, in import_from_string return import_string(val) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\module_loading.py", line 30, in import_string return cached_import(module_path, class_name) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\module_loading.py", line 15, in cached_import import_module(module_path) File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework_jwt\authentication.py", line 4, in <module> from django.utils.encoding import smart_text ImportError: cannot import name 'smart_text' from 'django.utils.encoding' (C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\encoding.py) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\threading.py", line 1009, in _bootstrap_inner self.run() File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\threading.py", line 946, in run self._target(*self._args, **self._kwargs) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\core\management\commands\runserver.py", line 124, in inner_run self.check(display_num_errors=True) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\core\management\base.py", line 438, in check all_issues = checks.run_checks( File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\core\checks\registry.py", line 77, in run_checks new_errors = check(app_configs=app_configs, databases=databases) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\core\checks\urls.py", line 13, in check_url_config return check_resolver(resolver) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\core\checks\urls.py", line 23, in check_resolver return check_method() File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\urls\resolvers.py", line 448, in check for pattern in self.url_patterns: File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\urls\resolvers.py", line 634, in url_patterns patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\urls\resolvers.py", line 627, in urlconf_module return import_module(self.urlconf_name) File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\Users\user\yb\django_askcompany\askcompany\Scripts\_askcompany8\_askcompany8\urls.py", line 7, in <module> path('accounts/', include('accounts.urls')), File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\urls\conf.py", line 34, in include urlconf_module = import_module(urlconf_module) File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "C:\Users\user\yb\django_askcompany\askcompany\Scripts\_askcompany8\accounts\urls.py", line 1, in <module> from rest_framework.authtoken.views import obtain_auth_token File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\authtoken\views.py", line 6, in <module> from rest_framework.schemas import ManualSchema File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\schemas\__init__.py", line 33, in <module> authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES, File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\settings.py", line 225, in __getattr__ val = perform_import(val, attr) File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\settings.py", line 168, in perform_import return [import_from_string(item, setting_name) for item in val] File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\settings.py", line 168, in <listcomp> return [import_from_string(item, setting_name) for item in val] File "C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\rest_framework\settings.py", line 180, in import_from_string raise ImportError(msg) ImportError: Could not import 'rest_framework_jwt.authentication.JSONWebTokenAuthentication' for API setting 'DEFAULT_AUTHENTICATION_CLASSES'. ImportError: cannot import name 'smart_text' from 'django.utils.encoding' (C:\Users\user\yb\django_askcompany\askcompany\lib\site-packages\django\utils\encoding.py).
 
가상환경에서 사용되는 버전은 다음과 같습니다.
 
늘 빠르고 친절한 답변에 감사드립니다.
pythondjangoreactdocker

Câu trả lời 5

0

colock1232765님의 프로필 이미지
colock1232765
Người đặt câu hỏi

허.. 확인했습니다 ㅠㅠ print문을 넣어도 출력되는 부분이 없었고

cmd에서 python test_token.py를 입력하니까 일단 401을 받았습니다.. 허허.. 진짜 삽질이였네요 ㅠㅠ

감사합니다.. 401을 받은 이유는 한번 더 찾아봐야겠네요.. 혹시 찾게되면 이 댓글을 수정해서 달아놓겠습니다. 

pyhub님의 프로필 이미지
pyhub
Người chia sẻ kiến thức

토큰이 만료되었을 경우 401 응답을 받을 수 있습니다.

이 모든 것이 실력향상의 밑거름이 되실 것입니다. 화이팅입니다. :-)

0

colock1232765님의 프로필 이미지
colock1232765
Người đặt câu hỏi

개인적으로 일이 있어서 답변을 늦게 확인했네요 우선 답변에 감사드립니다.

해당 강의 15:06초 즈음에 선생님께서 test_token.py를 실행시켜서 , 응답을 받으시는 부분이 있습니다.

simple_jwt를 적용해서 그부분을 동일하게 수행하고, 또 강의에서 처럼 동일한 딕셔너리 형태의 응답을 받기를 기대했는데

이런식으로 수행을 해봐도 아무런 응답이 되돌아 오지 않았습니다.

 

우선 서버는 켜져있는 것을 확인했고, settings.py역시 방금 한번 더 확인했는데, 선생님께서 바로 위에  올려주신 부분과 동일하게 처리되어 있습니다. 혹시몰라 토큰의 유효기간과 관련된 부분도 훨씬 더 긴 시간의 값을 주었습니다.

 

token은 일단 access token과 refresh token을 다음과 같이 받아서 

test_token.py에 복사해서 넣어두었습니다.

현재 제 test_token.py의 내용은 다음과 같습니다

import requests
 
#JWT
JWT_ACCESS_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQ4MDk4NzcxLCJpYXQiOjE2NDgwOTUxNzEsImp0aSI6IjMzYTM4ODU1MTI3ZTRhYWJiNzZkNmZhNWI3NTgwZjM1IiwidXNlcl9pZCI6Mn0.Z1mjp40YD6Eg0hQK01-Fp5FzDnk08G0Gfj54F1xtqH8"
JWT_REFRESH_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0ODM1NDM3MSwiaWF0IjoxNjQ4MDk1MTcxLCJqdGkiOiIwN2RjMGY0MDZhMDA0YzRiOWVkNmJlN2Q0MTE2NjJjMSIsInVzZXJfaWQiOjJ9.Qtq40KFnvG994OhlwXFoL8f_nPOUR4_lwKlRmqiJiYs"
 
#JWT헤더
#참고로 bearer : JWT 또는 OAuth토큰을 사용한다는 뜻임
jwt_headers={
    "Authorization": f"Bearer {JWT_ACCESS_TOKEN}"}


res = requests.get("http://localhost:8000/post/1",headers=jwt_headers)

print(res)

강의 마지막부분에서 자꾸 막혀서 자꾸 질문드리는게 죄송하네요 ㅠㅠ 늘 답변주셔서 감사합니다!

 

pyhub님의 프로필 이미지
pyhub
Người chia sẻ kiến thức

안녕하세요.

해당 스크립트를 실행하셨을 때, 코드 끝에 print(res) 로 기입하셨는 데, 서버로부터 응답을 받았다면 무엇이라도 출력이 되어야 합니다.

그런데, 아래와 같이 아무 것도 출력이 안 되는 것은 파이썬 스크립트가 실행이 안 된 것은 아닐까요.

코드 시작과 중간 중간에 print("코드 시작점") 과 같이 디버깅 목적으로 print 구문을 넣어서, 해당 내용이 출력되는 지 확인해보세요. 아마도 출력되는 내용이 없지 않을까 싶구요.

파이썬 스크립트를 실행하실 때 test_token.py 명령으로 하셨는 데, 윈도우에서 이는 .py 확장자와 연결된 연결 프로그램이 실행됩니다. 파이썬이 연결되었다면 파이썬이 실행될 수도 있지만, 메모장이 연결되었다면 메모장이 뜰 수도 있습니다.

파이썬에서는 필히 python test_token.py 와 같이 python 인터프리터에게 실행할 파일의 위치를 알려주는 방식으로 실행해주시는 것이 OS 막론하고 보다 명확한 실행방법입니다. 그래야만 내가 원하는 파이썬 인터프리터를 통해 파이썬 코드가 실행됩니다.

화이팅입니다.

0

pyhub님의 프로필 이미지
pyhub
Người chia sẻ kiến thức

안녕하세요.

access key를 받으시고 어떤 응답을 기대하셨고, 어떤 응답이 오시나요? 단순히 안된다라고 하시기보다, 예상하시는 결과와 현재의 결과를 설명해주셔야만 보다 좋은 답변을 얻으실 수 있습니다. // 의사도 증상을 알아야 진단을 하는 데, 아프다고만 하면 진단할 수가 없는 것과 같은 이치입니다.

현재의 상황을 파악하시는 연습이 되셔야, 저의 답변이 보다 도움이 되실 것입니다.

저의 경우, djangorestframework-simplejwt 를 설정하고, 아래의 authentication/permission 설정을 하고, 구현된 apiview에서 Authorization 헤더에 Bearer와 함께 jwt access token을 설정하고 요청하여 200 응답을 받았습니다.

장고에는 수많은 라이브러리가 있지만, 단순히 복&붙만으로 동작만을 확인하고 넘어가면 나중에 이슈가 생겼을때 대응하기 힘듭니다. 수많은 라이브러리를 통해 우리가 개발을 보다 수월하게 할 수 있지만, 이는 우리가 개발할 공수를 줄여주는 것일 뿐, 그 라이브러리를 잘 파악할 필요는 있습니다. // 내공을 쌓아가는 거죠.

차근차근 파악해보세요.

화이팅입니다. :-)

0

colock1232765님의 프로필 이미지
colock1232765
Người đặt câu hỏi

감사합니다 선생님~ 말씀대로 simple_jwt를 적용시켜보았는데요

설정을 하고 토큰을 잘받고, cpython에 진입해서 token을 뜯어보는 것 까지는 다 잘 실행이 되엇는데요

강의중에 test_token.py를 만들고 requests.get을 활용해서 응답을 받는 부분이 안되더라구요

import requests
JWT_ACCESS_TOKEN = "ey..."

#header
jwt_headers={
    "Authorization": f"Bearer {JWT_ACCESS_TOKEN}"}
   
res = requests.get("http://localhost:8000/post/1",headers = jwt_headers)
print(res)

이렇게 저렇게 찾아보다가 header의 authorization에 bearer를 넣어서(이 bearer가 jwt타입의 토큰을 사용한다는 뜻이더군요!) 하면 다른 분들의 코드에서는 잘 작동하는 것 같은데, 저는 응답이 돌아오지를 않네요.. 토큰의 유효기간 문제는 아닌 듯 합니다. 

혹시 괜찮으시면 키워드를 던져주실 수 있으실까요? 어떤 부분을 찾아봐야할지를 잘 모르겠네요 ㅠㅠ

 

 

0

pyhub님의 프로필 이미지
pyhub
Người chia sẻ kiến thức

안녕하세요.

강의에서 소개해드린 django-rest-framework-jwt 라이브러리는 장고 3.x 버전까지 지원합니다. django-rest-framework-jwt 라이브러리 내에 사용된 django api가 장고 버전4부터 없어져서 발생하는 import error 입니다.

관련 코드 : https://github.com/jpadilla/django-rest-framework-jwt/blob/master/rest_framework_jwt/authentication.py#L4

위 링크의 from django.utils.encoding import smart_text API는 장고 버전3까지 유효하며, 장고 4부터는 from django.utils.encoding import force_str 로 사용하여야 하거든요.

현재 장고 버전 4를 설치하셨는 데 강의에서는 장고 버전 3를 설치해서 진행을 하였습니다. 그래서 강의대로 django-rest-framework-jwt 라이브러리를 진행하실 경우, 장고 버전 3로 학습해주시길 권장드립니다. 학습 이후에 라이브러리 버전을 올려주세요.

 

django-rest-framework-jwt 라이브러리는 현재는 더 이상 유지보수가 되지 않고, django-restframework-jwt 개발자는 대안으로 drf-jwt 라이브러리djangorestframework-simplejwt 라이브러리를 제시하고 있습니다.

관련 이슈 : https://github.com/jpadilla/django-rest-framework-jwt/issues/484

학습 이후에 drf-jwt 라이브러리djangorestframework-simplejwt 라이브러리를 적용해보실 수 있겠는 데요.

  • drf-jwt 라이브러리는 django-rest-framework-jwt 라이브러리의 Fork 버전이므로, 장고4로 올리셔도 강의에서 언급한 설정을 그대로 가져가실 수 있구요.
  • djangorestframework-simplejwt 라이브러리는 다른 라이브러리이므로 설정이 다릅니다. 하지만 설정이 크게 다르지 않기에 공식문서를 보시고 적용해보시기에 무리가 없으실 것입니다. 하지만 세부 설정은 조금 다르기에 매뉴얼을 차근차근 살펴보셔야 합니다.

 

화이팅입니다. :-)

Hình ảnh hồ sơ của colock1232765
colock1232765

câu hỏi đã được viết

Đặt câu hỏi