url 오타도 아냐... 모델 import, view import 문제가 있는 것도 아냐... 왜 문제가 있는지 모르겠어서 답답할 따름인 내 코드. 차근차근 해결 시도를 해본 것을 풀어보겠다.
-/wordcloud_network_web (프로젝트 폴더)
-/wordcloud (워드클라우드 앱 폴더)
-/users (사용자 앱 폴더)
사용자 앱을 따로 만들어둔 이유는 이게 데이터 분석을 진행하는 웹 애플리케이션인데 사용자 데이터가 엄청 크고 관련 작업이 많아질 것 같아 지레 겁을 먹었기 때문이다. 앱 간의 연관이 낮아야 진정한 모듈화라고 할 수 있지만... 일단은 이렇게 진행하고 있다.
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns+=[path('',include('users.urls'))]
urlpatterns = [
path('', UserView.as_view(),name="users"),
]
class UserView(APIView):
def get(self,request):
users=get_list_or_404(UserModel)
serializer=UserSerializer(users)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
print("??")
print(UserModel.objects.filter(hierarchy="사원"))
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# Create your models here.
class UserModel(models.Model):
employeenumber=models.IntegerField()
name=models.CharField(max_length=100)
age=models.IntegerField()
hierarchy=models.CharField(max_length=100)
class UserSerializer(serializers.ModelSerializer):
def __init__(self):
#파일 불러오기
df=pd.read_csv('IBM-HR-Employee-Attrition_cat2num.csv')
#소문자화 함수 정의하기
l_case_func = str.lower
#열 이름 소문자화하기
df_lower =df.rename(columns = l_case_func)
#not unique error가 났지만 unique함...
print(len(df_lower['employeenumber'].unique())==len(df_lower['employeenumber']))
#모델에 넣기
UserModel.objects.bulk_create(
UserModel(**vals) for vals in df_lower.to_dict('records')
)
class Meta:
model=UserModel
fields=["name","hierarchy"]
lookup_field=["hierarchy"]
def get_queryset(self):
group = self.kwargs["hierarchy"]
return UserModel.objects.all() #(group = group) # return a queryset
INSTALLED_APPS 목록에 멀쩡하게 'users'가 존재함
그래서 else문을 붙여놓았는데 프린트 되는게 없다.
그래서 urls.py구나 했다.
프로젝트 폴더에 include(users.urls)를 보면 앱 이름도 오타 없이 users라고 잘 썼고, urls.py 이름도 오타가 없다. 그리고 혹시 몰라 프로젝트 urls.py에서도 users.url을 ''으로 빈 스트링으로 path를 등록해두었고, 앱 urls.py에서도 UserModel.as_view()를 ''으로 빈 스트링으로 등록해두었기 때문에 원래라면 127.0.0.1:8000/ 경로에 가면 404 에러가 나면 안된다.
하지만 난다.
근데 에러 메세지를 자세히 보면 그냥 404가 아니라 9944가 따라붙길래 한 번 찾아봤다.
그런데 오히려 다른 문제 지점을 찾았다.
https://stackoverflow.com/questions/67215329/why-am-i-getting-error-404-in-my-django-project-when-everything-seems-correct
위 stack overflow에서 짚어준 게 아래와 같다.
냅다 get_model_or_404() 없애버리고
users=UserModel
으로 바꾸어줬더니 제대로 된 에러(?)가 등장합니다.
그... 제가 딱 self만 넣어두긴 했는데 뭔가 restframework serializer는 디폴트로 뭐가 더 들어오나봅니다.
아래 링크 참고해서 user 앱 폴더의 serializers.py를 바꿔줬습니다.
https://www.reddit.com/r/django/comments/q5q2o6/init_function_inside_serializer_class_in_django/
class UserSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
#파일 불러오기
df=pd.read_csv('F:\\9DevPortfolio\\2023\\2308_KB Future Finance AI\\KBFFAI\\AI\\Dataset\\IBM-HR-Employee-Attrition_cat2num.csv')
#소문자화 함수 정의하기
l_case_func = str.lower
#열 이름 소문자화하기
df_lower =df.rename(columns = l_case_func)
#모델에 넣기
UserModel.objects.bulk_create(
UserModel(**vals) for vals in df_lower.to_dict('records')
)
class Meta:
model=UserModel
fields=["name","hierarchy"]
lookup_field=["hierarchy"]
def get_queryset(self):
group = self.kwargs["hierarchy"]
return UserModel.objects.all() #(group = group) # return a queryset
다른 에러가 나는군요
아래 링크를 보니까 view 클래스에서 serializer를 초기화 할 때 model object를 넘겨줘야 하는데 그렇지 않으면 이런 에러가 난다고 합니다.
https://stackoverflow.com/questions/29731013/django-rest-framework-cannot-call-is-valid-as-no-data-keyword-argument
그런데 저는 UserModel 자체를 넘겨줬거든요. User.objects.all()과 같이 여러 개의 instance를 넘겨줘도 괜찮은 걸까요? 아니면 저는 serializer의 __init__을 재정의하여 첫 serializer instance 초기화시 입력값과 무관하게 pandas dataframe으로부터 instance를 bulk_create하게 만들어놓았으니 아예 __init__에서 args,kwargs를 빼버리고 serializer instance 초기화도 매개변수 없이 진행하도록 바꾸어야 할까요?
전자보다 후자가 이론적 배경이 있는 해결 방법인 것 같아서 해보겠습니다.
에러는 그대로 유지됐지만, 이번에 하나 print 문을 추가했었거든요? views.py에서 serializer.data를 프린트하게 둔 구문입니다.
앱 폴더의 views.py 업데이트 버전
class UserView(APIView):
def get(self,request):
#users=UserModel
serializer=UserSerializer()
print(serializer.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
print("??")
print(UserModel.objects.filter(hierarchy="사원"))
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
아래와 같은 게 프린트 되었습니다.
{'name': '<django.db.models.query_utils.DeferredAttribute object at 0x000001F89620FDF0>', 'hierarchy': '<django.db.models.query_utils.DeferredAttribute object at 0x000001F89620FC40>'}
보면 제가 예상한 것과 달리 pandas dataframe에 있던 정보가 아닙니다. DeferredAttribute object를 찾아봐야겠습니다.
감사합니다. 이런 정보를 나눠주셔서 좋아요.