Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 프로그래머스
- greedy
- lol
- sort
- git
- 코딩테스트
- 탐욕알고리즘
- 자바
- Django
- 코딩테스트준비
- 스파르타내일배움캠프
- python
- API
- 그리디알고리즘
- 백준
- java
- 롤
- 스파르타내일배움캠프TIL
- 장고
- 내일배움캠프
- 파이썬
- programmers
- 알고리즘
- 그리디
- github
- Riot
- SQL
- 리그오브레전드
- 라이엇
- drf
Archives
- Today
- Total
Lina's Toolbox
[Django] TypeError : Cannot filter a query once a slice has been taken. 본문
스파르타 내일 배움 캠프 AI 웹개발 과정/troubleshooting
[Django] TypeError : Cannot filter a query once a slice has been taken.
Woolina 2024. 10. 11. 17:22
raise TypeError("Cannot filter a query once a slice has been taken.")
TypeError: Cannot filter a query once a slice has been taken.
[11/Oct/2024 17:14:42] "POST /auth/users/recommendations/ HTTP/1.1" 500 106817
이런 에러가 발생했다.
이미 슬라이싱이 된 쿼리는 filter를 할수 없다고?
def post(self, request, *args, **kwargs):
# 초기화
matching_reviewee_id = None
# 요청에서 필터링 값 가져오기
riot_tiers = request.data.getlist('riot_tier', [])
positions = request.data.getlist('positions', [])
filter_fields = request.data.getlist('filter_fields', [])
user_preference = request.data.get('user_preference', '')
# 기본 유저 리스트 가져오기
users = User.objects.all()
# 1. 기본 필터링 (티어와 포지션에 따라 필터링)
if riot_tiers:
users = users.filter(riot_tier__in=riot_tiers)
if positions:
users = users.filter(positions__position_name__in=positions)
# 2. 평가 필드 필터링
if filter_fields:
# 필터링 조건 추가
filter_conditions = {}
for field in filter_fields:
if hasattr(Evaluations, field):
filter_conditions[f'evaluations__{field}__gte'] = 1 # 필드 값이 1 이상인 경우
# 유저 필터링
users = users.filter(**filter_conditions)
# 평가 항목이 있는 유저만 필터링 후 정렬
users = users.filter(evaluations__isnull=False).annotate(
evaluations_count=models.Count('evaluations')
).order_by(*[f'-evaluations__{field}' for field in filter_fields]).distinct()
# 상위 3명만 선택
users = users[:3]
# 리뷰 데이터 가져오기
all_reviews = Articles.objects.all().values('content', 'reviewee')
reviews_text = "\n".join([f"Review ID: {review['reviewee']} - {review['content']}" for review in all_reviews])
# 3. 사용자 입력 텍스트 처리
if user_preference:
# OpenAI API를 사용하여 유저의 선호도에 맞는 리뷰 분석
system_instructions = """
You are tasked with finding the most relevant review for a user based on their preferences.
Based on the user's preference, identify the review that best matches the following description: {user_preference}.
Here are all the reviews:
{reviews_text}.
Provide only the matching reviewee's ID or IDs in a comma-separated format (e.g., 1 or 1, 2) without any additional text.
"""
prompt = system_instructions.format(
user_preference=user_preference,
reviews_text=reviews_text
)
user_preference_analysis = ask_chatgpt(user_message=prompt, system_instructions="")
print('user_preference_analysis:', user_preference_analysis)
# 응답 포맷 확인 및 처리
try:
if "Review ID:" in user_preference_analysis:
# "Review ID: 1, 2" 형식 처리
matching_reviewee_ids = [int(id.strip()) for id in user_preference_analysis.split(":")[1].split(",")]
else:
# "1, 2" 형식 처리
matching_reviewee_ids = [int(id.strip()) for id in user_preference_analysis.split(",")]
except (ValueError, IndexError) as e:
raise ValueError(f"Unexpected response format from OpenAI: {user_preference_analysis}") from e
# 유저 필터링
if matching_reviewee_ids: # 리스트가 비어있지 않은 경우
users = users.filter(id__in=matching_reviewee_ids)
# 직렬화하여 응답
serializer = UserSerializer(users, many=True)
return render(request, 'users/matching_result.html', {'users': serializer.data})
users = users[:3] 로 슬라이싱을 이미 한 후에,
users = users.filter(id__in=matching_reviewee_ids) 이렇게 다시 필터링을 하는 게 문제였다.
그래서 상위 3명을 추출하는 코드를 리턴 직전으로 순서를 바꿔줬다.
def post(self, request, *args, **kwargs):
# 초기화
matching_reviewee_id = None
# 요청에서 필터링 값 가져오기
riot_tiers = request.data.getlist('riot_tier', [])
positions = request.data.getlist('positions', [])
filter_fields = request.data.getlist('filter_fields', [])
user_preference = request.data.get('user_preference', '')
# 기본 유저 리스트 가져오기
users = User.objects.all()
# 1. 기본 필터링 (티어와 포지션에 따라 필터링)
if riot_tiers:
users = users.filter(riot_tier__in=riot_tiers)
if positions:
users = users.filter(positions__position_name__in=positions)
# 2. 평가 필드 필터링
if filter_fields:
# 필터링 조건 추가
filter_conditions = {}
for field in filter_fields:
if hasattr(Evaluations, field):
filter_conditions[f'evaluations__{field}__gte'] = 1 # 필드 값이 1 이상인 경우
# 유저 필터링
users = users.filter(**filter_conditions)
# 평가 항목이 있는 유저만 필터링 후 정렬
users = users.filter(evaluations__isnull=False).annotate(
evaluations_count=models.Count('evaluations')
).order_by(*[f'-evaluations__{field}' for field in filter_fields]).distinct()
# 상위 3명만 선택
users = users[:3]
# 리뷰 데이터 가져오기
all_reviews = Articles.objects.all().values('content', 'reviewee')
reviews_text = "\n".join([f"Review ID: {review['reviewee']} - {review['content']}" for review in all_reviews])
# 3. 사용자 입력 텍스트 처리
if user_preference:
# OpenAI API를 사용하여 유저의 선호도에 맞는 리뷰 분석
system_instructions = """
You are tasked with finding the most relevant review for a user based on their preferences.
Based on the user's preference, identify the review that best matches the following description: {user_preference}.
Here are all the reviews:
{reviews_text}.
Provide only the matching reviewee's ID or IDs in a comma-separated format (e.g., 1 or 1, 2) without any additional text.
"""
prompt = system_instructions.format(
user_preference=user_preference,
reviews_text=reviews_text
)
user_preference_analysis = ask_chatgpt(user_message=prompt, system_instructions="")
print('user_preference_analysis:', user_preference_analysis)
# 응답 포맷 확인 및 처리
try:
if "Review ID:" in user_preference_analysis:
# "Review ID: 1, 2" 형식 처리
matching_reviewee_ids = [int(id.strip()) for id in user_preference_analysis.split(":")[1].split(",")]
else:
# "1, 2" 형식 처리
matching_reviewee_ids = [int(id.strip()) for id in user_preference_analysis.split(",")]
except (ValueError, IndexError) as e:
raise ValueError(f"Unexpected response format from OpenAI: {user_preference_analysis}") from e
# 유저 필터링
if matching_reviewee_ids: # 리스트가 비어있지 않은 경우
users = users.filter(id__in=matching_reviewee_ids)
# 상위 3명만 선택
users = users[:3]
# 직렬화하여 응답
serializer = UserSerializer(users, many=True)
return render(request, 'users/matching_result.html', {'users': serializer.data})
그랬더니 문제없이 잘 작동했다!
이미 슬라이싱된 쿼리는 다시 필터링 할 수 없다!!!
필터링을 먼저 한 후에 슬라이싱을 적용하기!
기억!!