-
Notifications
You must be signed in to change notification settings - Fork 0
써치 페이지 #613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
써치 페이지 #613
Changes from all commits
49a5ce8
8ce4339
37378e4
21c6fe2
f032711
f01e070
51016c3
2f27127
957d6ab
1ca8603
fb223d0
5cf9386
bbd3e0d
8e08ef3
a41ef2c
7a74d43
be7e771
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,7 +8,7 @@ | |
| path("reorder/", views.ProjectReorderView.as_view()), | ||
| path("", views.ProjectList.as_view()), | ||
| path("inbox/", views.InboxProjectDetail.as_view()), | ||
| path("<str:id>/", views.ProjectDetail.as_view()), | ||
| path("<str:id>/", views.ProjectDetail.as_view()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CI 파이프라인 실패 원인: 마지막 항목의 후행 쉼표(trailing comma) 제거
Proposed fix- path("<str:id>/", views.ProjectDetail.as_view())
+ path("<str:id>/", views.ProjectDetail.as_view()),🤖 Prompt for AI Agents |
||
| ] | ||
|
|
||
| urlpatterns = format_suffix_patterns(urlpatterns) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from django.contrib import admin | ||
|
|
||
| # Register your models here. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| from django.apps import AppConfig | ||
|
|
||
|
|
||
| class SearchConfig(AppConfig): | ||
| default_auto_field = 'django.db.models.BigAutoField' | ||
| name = 'search' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from django.db import models | ||
|
|
||
| # Create your models here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| from rest_framework import serializers | ||
|
|
||
| from projects.models import Project | ||
| from drawers.models import Drawer | ||
| from tasks.models import Task | ||
|
|
||
| class ProjectSearchSerializer(serializers.ModelSerializer): | ||
| class Meta: | ||
|
Check failure on line 8 in backend/search/serializers.py
|
||
| model = Project | ||
| exclude = () | ||
|
|
||
| class DrawerSearchSerializer(serializers.ModelSerializer): | ||
| color = serializers.CharField(source="project.color", read_only=True) | ||
|
|
||
| class Meta: | ||
|
Check failure on line 15 in backend/search/serializers.py
|
||
| model = Drawer | ||
| exclude = () | ||
|
|
||
| class TaskSearchSerializer(serializers.ModelSerializer): | ||
| color = serializers.CharField(source="drawer.project.color", read_only=True) | ||
|
|
||
| class Meta: | ||
|
Check failure on line 22 in backend/search/serializers.py
|
||
| model = Task | ||
| exclude = () | ||
|
Comment on lines
+7
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
세 직렬화기 모두 최소 권한 원칙에 따라 또한, 파이프라인의 pyright 오류를 해결하려면 기존 코드베이스 패턴( ProjectSearchSerializer 수정 예시 class ProjectSearchSerializer(serializers.ModelSerializer):
- class Meta:
+ class Meta: # pyright: ignore [reportIncompatibleVariableOverride]
model = Project
- exclude = ()
+ fields = ["id", "name", "color", "type", "privacy"]🧰 Tools🪛 GitHub Check: type[failure] 22-22: [failure] 15-15: [failure] 8-8: 🤖 Prompt for AI Agents |
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,38 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from django.db.models import Q, F, Value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from projects.models import Project | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from drawers.models import Drawer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from tasks.models import Task | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .serializers import ProjectSearchSerializer, DrawerSearchSerializer, TaskSearchSerializer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SCOPE_BITMASK = {"task": 1, "drawer": 2, "project": 4} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SEARCH_PREVIEW_LIMIT = 4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def global_search(query, scope): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| results = dict() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # TODO: global한 결과를 내놓기에 각 결과가 FK object 전체를 들고 오는 것보다 필요한 color만 쓰는 것이 낫다 판단함. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # 검색 옵션에 따라 project, drawer object를 같이 반환하도록 하는 것을 고려 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # drawer serializer 참고 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targets = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "task": {"objects": Task.objects.select_related("drawer__project"), "serializer": TaskSearchSerializer}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "drawer": {"objects": Drawer.objects.select_related("project"), "serializer": DrawerSearchSerializer}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "project": {"objects": Project.objects, "serializer": ProjectSearchSerializer}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for key, value in targets.items(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if scope & SCOPE_BITMASK[key]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_set = value["objects"].filter( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Q(name__icontains=query) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| count = query_set.count() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if count > SEARCH_PREVIEW_LIMIT: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query_set = query_set[:SEARCH_PREVIEW_LIMIT] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = value["serializer"](query_set, many=True).data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| results[key] = {"data": data, "count": count} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| results[key] = {"data": [], "count": 0} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용자 격리 없음 — 전체 사용자 데이터 노출 (보안 취약점)
함수 시그니처에 Proposed fix-def global_search(query, scope):
+def global_search(query, scope, user):
results = dict()
targets = {
- "task": {"objects": Task.objects.select_related("drawer__project"), "serializer": TaskSearchSerializer},
- "drawer": {"objects": Drawer.objects.select_related("project"), "serializer": DrawerSearchSerializer},
- "project": {"objects": Project.objects, "serializer": ProjectSearchSerializer},
+ "task": {"objects": Task.objects.filter(user=user).select_related("drawer__project"), "serializer": TaskSearchSerializer},
+ "drawer": {"objects": Drawer.objects.filter(user=user).select_related("project"), "serializer": DrawerSearchSerializer},
+ "project": {"objects": Project.objects.filter(user=user), "serializer": ProjectSearchSerializer},
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return results | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from django.test import TestCase | ||
|
|
||
| # Create your tests here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| from django.urls import path | ||
|
|
||
| from rest_framework.urlpatterns import format_suffix_patterns | ||
|
|
||
| from . import views | ||
|
|
||
| urlpatterns = [ | ||
| path("", views.GlobalSearchView.as_view()), | ||
| ] | ||
|
|
||
| urlpatterns = format_suffix_patterns(urlpatterns) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||||||||||||||||||||
| from rest_framework import mixins, generics, status | ||||||||||||||||||||||||||||||||||||||||||
| from rest_framework.response import Response | ||||||||||||||||||||||||||||||||||||||||||
| from rest_framework.exceptions import ValidationError | ||||||||||||||||||||||||||||||||||||||||||
| from rest_framework.pagination import PageNumberPagination | ||||||||||||||||||||||||||||||||||||||||||
| from rest_framework.views import APIView | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from django.db.models import Q, F, Value | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from projects.models import Project | ||||||||||||||||||||||||||||||||||||||||||
| from drawers.models import Drawer | ||||||||||||||||||||||||||||||||||||||||||
| from tasks.models import Task | ||||||||||||||||||||||||||||||||||||||||||
| from .serializers import ProjectSearchSerializer, DrawerSearchSerializer, TaskSearchSerializer | ||||||||||||||||||||||||||||||||||||||||||
| from .service import global_search | ||||||||||||||||||||||||||||||||||||||||||
| from projects.exceptions import ProjectNameDuplicate | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| from api.permissions import IsUserOwner | ||||||||||||||||||||||||||||||||||||||||||
| from api.exceptions import UnknownError | ||||||||||||||||||||||||||||||||||||||||||
| from api.serializers import ReorderSerializer | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| class SearchPagination(PageNumberPagination): | ||||||||||||||||||||||||||||||||||||||||||
| page_size = 20 | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # page size 조절 가능하게 | ||||||||||||||||||||||||||||||||||||||||||
| page_size_query_param = "page_size" | ||||||||||||||||||||||||||||||||||||||||||
| max_page_size = 100 | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # 하나의 view에서 여러 serializer를 부를 거라 복잡해도 그냥 APIView가 적합할 거 같음 | ||||||||||||||||||||||||||||||||||||||||||
| # 파라미터 종류가 많아지면 django-filter를 적극적으로 고려해 보자... | ||||||||||||||||||||||||||||||||||||||||||
| class ProjectSearchView(APIView): | ||||||||||||||||||||||||||||||||||||||||||
| def get(self, request, *args, **kwargs): | ||||||||||||||||||||||||||||||||||||||||||
| q = request.query_params.get("query", "").strip() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # query가 비어있으면 빈 결과 반환 | ||||||||||||||||||||||||||||||||||||||||||
| # TODO: 나중에 프로젝트 페이지와 합치게 되면 전부 보이는 걸로 바뀌어야 할 지도? | ||||||||||||||||||||||||||||||||||||||||||
| if not q: | ||||||||||||||||||||||||||||||||||||||||||
| return Response({ | ||||||||||||||||||||||||||||||||||||||||||
| "projects": [], | ||||||||||||||||||||||||||||||||||||||||||
| "drawers": [], | ||||||||||||||||||||||||||||||||||||||||||
| "tasks": [], | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| project_qs = Project.objects.filter( | ||||||||||||||||||||||||||||||||||||||||||
| Q(name__icontains=q) | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| drawer_qs = Drawer.objects.select_related("project").filter( | ||||||||||||||||||||||||||||||||||||||||||
| Q(name__icontains=q) | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| task_qs = Task.objects.select_related("drawer__project").filter( | ||||||||||||||||||||||||||||||||||||||||||
| Q(name__icontains=q) | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| project_data = ProjectSearchSerializer(project_qs, many=True).data | ||||||||||||||||||||||||||||||||||||||||||
| drawer_data = DrawerSearchSerializer(drawer_qs, many=True).data | ||||||||||||||||||||||||||||||||||||||||||
| task_data = TaskSearchSerializer(task_qs, many=True).data | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return Response({ | ||||||||||||||||||||||||||||||||||||||||||
| "projects": project_data, | ||||||||||||||||||||||||||||||||||||||||||
| "drawers": drawer_data, | ||||||||||||||||||||||||||||||||||||||||||
| "tasks": task_data, | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
이 뷰가 현재 PR에서 의도된 기능이라면 URL 등록 및 사용자 필터를 추가하고, 그렇지 않다면 제거하는 것을 권장합니다. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # GlobalSearchView는 pagination X | ||||||||||||||||||||||||||||||||||||||||||
| class GlobalSearchView(APIView): | ||||||||||||||||||||||||||||||||||||||||||
| def get(self, request, *args, **kwargs): | ||||||||||||||||||||||||||||||||||||||||||
| query = request.query_params.get("keyword", "").strip() | ||||||||||||||||||||||||||||||||||||||||||
| # bitmask: project / drawer / task | ||||||||||||||||||||||||||||||||||||||||||
| scope = request.query_params.get("scope", "7").strip() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||
| scope = int(scope) | ||||||||||||||||||||||||||||||||||||||||||
| except ValueError: | ||||||||||||||||||||||||||||||||||||||||||
| return Response( | ||||||||||||||||||||||||||||||||||||||||||
| {"detail": "search_range must be an integer"}, | ||||||||||||||||||||||||||||||||||||||||||
| status=status.HTTP_400_BAD_REQUEST | ||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # query가 비어있으면 빈 결과 반환 | ||||||||||||||||||||||||||||||||||||||||||
| if not query: | ||||||||||||||||||||||||||||||||||||||||||
| return Response({ | ||||||||||||||||||||||||||||||||||||||||||
| "projects": {"data": [], "count": 0}, | ||||||||||||||||||||||||||||||||||||||||||
| "drawers": {"data": [], "count": 0}, | ||||||||||||||||||||||||||||||||||||||||||
| "tasks": {"data": [], "count": 0}, | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
| results = global_search(query, scope) | ||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
- results = global_search(query, scope)
+ results = global_search(query, scope, request.user)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return Response(results) | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+79
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 빈 쿼리 응답의 키 이름이 빈 쿼리일 때 반환하는 딕셔너리는 복수형 키( Proposed fix if not query:
return Response({
- "projects": {"data": [], "count": 0},
- "drawers": {"data": [], "count": 0},
- "tasks": {"data": [], "count": 0},
+ "project": {"data": [], "count": 0},
+ "drawer": {"data": [], "count": 0},
+ "task": {"data": [], "count": 0},
})📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import client from "@api/client" | ||
| import type { Base, PaginationData, Privacy } from "@api/common" | ||
|
Check failure on line 2 in frontend/src/api/search.api.ts
|
||
| import type { User } from "@api/users.api" | ||
|
|
||
| import type { PaletteColorName } from "@assets/palettes" | ||
| import { Project } from "@api/projects.api" | ||
| import { Drawer } from "@api/drawers.api" | ||
| import { Task } from "@api/tasks.api" | ||
|
|
||
| export interface DrawerSearchResult extends Drawer { | ||
| color: PaletteColorName | ||
| } | ||
|
|
||
| export type TaskSearchResult = Task & { | ||
| color: PaletteColorName | ||
| } | ||
|
|
||
| type ResultBlock<T> = { | ||
| data: T[] | ||
| count: number | ||
| } | ||
|
|
||
| export interface SearchResponse { | ||
| project: ResultBlock<Project> | ||
| drawer: ResultBlock<DrawerSearchResult> | ||
| task: ResultBlock<TaskSearchResult> | ||
| } | ||
|
|
||
| export type ProjectType = "inbox" | "regular" | "goal" | ||
|
|
||
| //export const getGlobalSearchResults = async (query: string, page: string) => { | ||
| export const getGlobalSearchResults = async (query: string) => { | ||
| const keyword = query | ||
| const res = await client.get<SearchResponse>(`search/`, { | ||
| params: { keyword }, | ||
| }) | ||
|
|
||
| return res.data | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
검색 직렬화기(Serializer) 중복:
backend/search/serializers.py에 이미 존재합니다.ProjectSearchSerializer,DrawerSearchSerializer,TaskSearchSerializer가 이 파일과backend/search/serializers.py에 모두 정의되어 있습니다.backend/search/serializers.py의 버전은DrawerSearchSerializer에project.color,TaskSearchSerializer에drawer.project.color를 포함하는 등 프론트엔드 요구사항에 맞는 구현이 되어 있습니다. 이 파일의 중복 정의는 제거하고, Line 4-5의Drawer,Taskimport도 함께 제거해야 합니다.수정 제안
그리고 Line 54-67의 세 직렬화기 클래스를 삭제합니다.
🧰 Tools
🪛 GitHub Actions: Backend
[error] 55-55: "Meta" overrides symbol of same name in class "ModelSerializer". "backend.projects.serializers.ProjectSearchSerializer.Meta" is not assignable to "rest_framework.serializers.ModelSerializer.Meta". Type "type[backend.projects.serializers.ProjectSearchSerializer.Meta]" is not assignable to type "type[rest_framework.serializers.ModelSerializer.Meta]" (reportIncompatibleVariableOverride)
🪛 GitHub Check: type
[failure] 65-65:
"Meta" overrides symbol of same name in class "ModelSerializer"
"backend.projects.serializers.TaskSearchSerializer.Meta" is not assignable to "rest_framework.serializers.ModelSerializer.Meta"
Type "type[backend.projects.serializers.TaskSearchSerializer.Meta]" is not assignable to type "type[rest_framework.serializers.ModelSerializer.Meta]" (reportIncompatibleVariableOverride)
[failure] 60-60:
"Meta" overrides symbol of same name in class "ModelSerializer"
"backend.projects.serializers.DrawerSearchSerializer.Meta" is not assignable to "rest_framework.serializers.ModelSerializer.Meta"
Type "type[backend.projects.serializers.DrawerSearchSerializer.Meta]" is not assignable to type "type[rest_framework.serializers.ModelSerializer.Meta]" (reportIncompatibleVariableOverride)
[failure] 55-55:
"Meta" overrides symbol of same name in class "ModelSerializer"
"backend.projects.serializers.ProjectSearchSerializer.Meta" is not assignable to "rest_framework.serializers.ModelSerializer.Meta"
Type "type[backend.projects.serializers.ProjectSearchSerializer.Meta]" is not assignable to type "type[rest_framework.serializers.ModelSerializer.Meta]" (reportIncompatibleVariableOverride)
🤖 Prompt for AI Agents