11import datetime
2+ from typing import List
23from uuid import UUID
34
4- from pydantic import field_validator
5+ from fastapi import Query
6+ from fastapi_filter .contrib .sqlalchemy import Filter
7+ from pydantic import ValidationInfo , field_validator
58
69from rating_api .exceptions import WrongMark
7- from rating_api .models import ReviewStatus
10+ from rating_api .models import Lecturer , ReviewStatus
811from rating_api .schemas .base import Base
912
1013
@@ -24,57 +27,13 @@ class CommentGet(Base):
2427 dislike_count : int
2528
2629
27- class CommentGetWithStatus (Base ):
28- uuid : UUID
29- user_id : int | None = None
30- create_ts : datetime .datetime
31- update_ts : datetime .datetime
32- subject : str | None = None
33- text : str
34- mark_kindness : int
35- mark_freebie : int
36- mark_clarity : int
37- mark_general : float
38- lecturer_id : int
30+ class CommentGetWithStatus (CommentGet ):
3931 review_status : ReviewStatus
40- like_count : int
41- dislike_count : int
4232
4333
44- class CommentGetWithAllInfo (Base ):
45- uuid : UUID
46- user_id : int | None = None
47- create_ts : datetime .datetime
48- update_ts : datetime .datetime
49- subject : str | None = None
50- text : str
51- mark_kindness : int
52- mark_freebie : int
53- mark_clarity : int
54- mark_general : float
55- lecturer_id : int
34+ class CommentGetWithAllInfo (CommentGet ):
5635 review_status : ReviewStatus
5736 approved_by : int | None = None
58- like_count : int
59- dislike_count : int
60-
61-
62- class CommentPost (Base ):
63- subject : str
64- text : str
65- create_ts : datetime .datetime | None = None
66- update_ts : datetime .datetime | None = None
67- mark_kindness : int
68- mark_freebie : int
69- mark_clarity : int
70- is_anonymous : bool = True
71-
72- @field_validator ('mark_kindness' , 'mark_freebie' , 'mark_clarity' )
73- @classmethod
74- def validate_mark (cls , value ):
75- if value not in [- 2 , - 1 , 0 , 1 , 2 ]:
76- raise WrongMark ()
77- return value
7837
7938
8039class CommentUpdate (Base ):
@@ -92,22 +51,16 @@ def validate_mark(cls, value):
9251 return value
9352
9453
95- class CommentImport (Base ):
96- lecturer_id : int
97- subject : str | None = None
98- text : str
54+ class CommentPost (CommentUpdate ):
9955 create_ts : datetime .datetime | None = None
10056 update_ts : datetime .datetime | None = None
101- mark_kindness : int
102- mark_freebie : int
103- mark_clarity : int
57+ is_anonymous : bool = True
10458
105- @field_validator ('mark_kindness' , 'mark_freebie' , 'mark_clarity' )
106- @classmethod
107- def validate_mark (cls , value ):
108- if value not in [- 2 , - 1 , 0 , 1 , 2 ]:
109- raise WrongMark ()
110- return value
59+
60+ class CommentImport (CommentUpdate ):
61+ lecturer_id : int
62+ create_ts : datetime .datetime | None = None
63+ update_ts : datetime .datetime | None = None
11164
11265
11366class CommentImportAll (Base ):
@@ -123,16 +76,10 @@ class CommentGetAll(Base):
12376
12477class CommentGetAllWithStatus (Base ):
12578 comments : list [CommentGetWithStatus ] = []
126- limit : int
127- offset : int
128- total : int
12979
13080
13181class CommentGetAllWithAllInfo (Base ):
13282 comments : list [CommentGetWithAllInfo ] = []
133- limit : int
134- offset : int
135- total : int
13683
13784
13885class LecturerUserCommentPost (Base ):
@@ -171,9 +118,63 @@ class LecturerPost(Base):
171118 timetable_id : int | None = None
172119
173120
174- class LecturerPatch (Base ):
121+ class LecturerPatch (LecturerPost ):
175122 first_name : str | None = None
176123 last_name : str | None = None
177124 middle_name : str | None = None
178- avatar_link : str | None = None
179- timetable_id : int | None = None
125+
126+
127+ class LecturersFilter (Filter ):
128+ subject : str = ''
129+ name : str = ''
130+ order_by : List [str ] = [
131+ 'mark_weighted' ,
132+ ]
133+
134+ @field_validator ("*" , mode = "before" , check_fields = False )
135+ def validate_order_by (cls , value , field : ValidationInfo ):
136+ return value
137+
138+ @field_validator ('order_by' , mode = 'before' )
139+ def check_order_param (cls , value : str ) -> str :
140+ """Проверяет, что значение поля (без +/-) входит в список возможных."""
141+ allowed_ordering = {
142+ "mark_weighted" ,
143+ "mark_kindness" ,
144+ "mark_freebie" ,
145+ "mark_clarity" ,
146+ "mark_general" ,
147+ "last_name" ,
148+ }
149+ cleaned_value = value .replace ("+" , "" ).replace ("-" , "" )
150+ if cleaned_value in allowed_ordering :
151+ return value
152+ else :
153+ raise ValueError (f'"order_by"-field must contain value from { allowed_ordering } .' )
154+
155+ def filter (self , query : Query ) -> Query :
156+ if self .subject :
157+ query = query .filter (self .Constants .model .search_by_subject (self .subject ))
158+ if self .name :
159+ query = query .filter (self .Constants .model .search_by_name (self .name ))
160+ return query
161+
162+ def sort (self , query : Query ) -> Query :
163+ if not self .ordering_values :
164+ return query
165+ elif len (self .ordering_values ) > 1 :
166+ raise ValueError ('order_by (хотя бы пока что) поддерживает лишь один параметр для сортировки!' )
167+
168+ for field_name in self .ordering_values :
169+ direction = True
170+ if field_name .startswith ("-" ):
171+ direction = False
172+ field_name = field_name .replace ("-" , "" ).replace ("+" , "" )
173+ if field_name .startswith ('mark_' ):
174+ query = query .order_by (* self .Constants .model .order_by_mark (field_name , direction ))
175+ else :
176+ query = query .order_by (* self .Constants .model .order_by_name (field_name , direction ))
177+ return query
178+
179+ class Constants (Filter .Constants ):
180+ model = Lecturer
0 commit comments