-
Notifications
You must be signed in to change notification settings - Fork 10
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
api: add search filter by class schedule and department #234
base: main
Are you sure you want to change the base?
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@@ -70,12 +68,15 @@ def get_disciplines_and_search_flag(self, request, name): | |||
search_by_teacher = True | |||
return disciplines, search_by_teacher | |||
|
|||
def get_serialized_data(self, filter_params: dict, search_by_teacher: bool, name: str) -> list: | |||
def get_serialized_data(self, filter_params: dict, search_by_teacher: bool, name: str, schedule=None, search_by_schedule=False) -> list: |
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.
Function get_serialized_data
has 5 arguments (exceeds 4 allowed). Consider refactoring.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #234 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 58 58
Lines 2016 2086 +70
=========================================
+ Hits 2016 2086 +70 ☔ View full report in Codecov by Sentry. |
…hub.com/unb-mds/2023-2-SuaGradeUnB into api/add-search-filter-by-class-schedule
Code Climate has analyzed commit 28c794d and detected 2 issues on this pull request. Here's the issue category breakdown:
View more on Code Climate. |
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.
Boa noite! Realizei algumas considerações a respeito do sistema e do código. Quando puder, poderia dar uma olhada?
@@ -21,7 +21,7 @@ | |||
from traceback import print_exception | |||
|
|||
MAXIMUM_RETURNED_DISCIPLINES = 15 | |||
ERROR_MESSAGE = "no valid argument found for 'search', 'year' or 'period'" | |||
ERROR_MESSAGE = "Bad search parameters or missing parameters" |
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.
Eu acredito que nesse caso, as mensagens de erro devem ser mais descritivas.
Ao realizar uma pesquisa, tive certa dificuldade em saber o que estava fazendo de errado.
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.
Olá, modificarei as mensagens para torná-las mais descritivas.
data_aux = [] | ||
for i in range(len(data)): | ||
if data[i]['classes'] == []: | ||
data_aux.append(data[i]) | ||
for i in data_aux: | ||
data.remove(i) |
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.
Não entendi o propósito dessas linhas de código. Poderia elaborar um pouco sobre?
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.
Olá, Caio! O propósito deste trecho de código é filtrar as disciplinas que por ventura tenham sido encontradas pelo nome, porém devido ao critério de horário, não possua nenhuma turma associada. Isso pode ocorrer caso o estudante pesquise por exemplo:
- Cálculo 1
- 234N23
e não exista nenhuma turma com esse horário. A ideia seria não retornar o objeto deDisciplines
com a lista declasses
vazia, pois pode comprometer a experiência do usuário.
Caso a pesquisa acima fosse modificada para
- Calc
- 234N23
existe a possibilidade de outras matérias possuírem turmas neste horário e, caso a matéria deCálculo 1
não fosse removida dodata
, o usuário iria receber uma lista de disciplinas onde uma delas não possui turmas.
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.
Entendi. Essa abordagem não é muito performática por conta das frequentes buscas lineares para remoção, e também das remoções (que será linear).
Acho que seria melhor algo desse tipo:
data = list(filter(lambda value: len(value) > 0, data))
search_by_schedule = True | ||
elif schedule and department_code: | ||
disciplines = filter_disciplines_by_schedule_and_department_code( | ||
schedule=schedule, department_code=department_code) | ||
search_by_schedule = True |
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.
O search_by_schedule = True
aparece duas vezes. Acho que poderia remover esses trechos do escopo local das estruturas de condição e adicionar o atributo da variável apenas uma vez em um escopo mais geral. O que acha?
def filter_disciplines_by_schedule_and_department_code(schedule: str, department_code: str) -> QuerySet: | ||
"""Filtra as disciplinas pelo horário.""" | ||
return Discipline.objects.filter(Q(classes__schedule__icontains=schedule) & Q(department__code=department_code)).distinct("id") |
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.
Não entendi muito bem o uso do filter_disciplines_by_schedule_and_department_code
em conjunto com o filter_classes_by_schedule
. Esse Q(classes__schedule__icontains=schedule)
não filtra as aulas através do código? Logo em seguida, é utilizada a outra função. Algum dos dois são inutilizados, não?
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.
Olá, Caio! A função filter_disciplines_by_schedule_and_department_code()
serve para encontrar disciplinas que possuam alguma turma com o horário especificado. Uma vez feito isso, antes de retornar a disciplina para o front-end, é necessário filtrar, dentre as turmas do objeto Discipline em questão, as turmas que coincidem com o horário especificado.
Algo parecido é feito na busca por professor, uma vez que encontramos disciplinas com turmas com o professor especificado, nós filtramos, dentre as turmas daquela disciplina, somente as turmas daquele professor.
Essa filtragem de turmas é feita dentro serializer após obter os objetos disciplines em questão.
class DisciplineSerializer(DisciplineSerializerSchedule):
classes = serializers.SerializerMethodField()
def get_classes(self, discipline: Discipline):
teacher_name = self.context.get('teacher_name')
schedule = self.context.get('schedule')
classes = discipline.classes.all() if hasattr(
discipline, 'classes') else Class.objects.none()
if teacher_name:
classes = dbh.filter_classes_by_teacher(
name=teacher_name, classes=classes)
if schedule:
classes = dbh.filter_classes_by_schedule(
schedule=schedule, classes=classes)
return ClassSerializer(classes, many=True).data
Não conheço uma maneira de filtrar os objetos classes
relacionados ao objeto discipline
diretamente na filtragem de objetos Discipline
utilizando o ORM padrão do Djano. Talvez seja interessante utilizar uma query em SQL que já realize a filtragem completa.
O que acha?
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.
Algo parecido é feito na busca por professor, uma vez que encontramos disciplinas com turmas com o professor especificado, nós filtramos, dentre as turmas daquela disciplina, somente as turmas daquele professor.
Entendi. Se já temos um sistema dessa forma, vamos manter então (pelo menos por enquanto).
Nunca tinha reparado, não me parece ser tão interessante seguir dessa maneira. Não estamos verificando esses atributos duas vezes?
Talvez seja interessante utilizar uma query em SQL que já realize a filtragem completa.
O que acha?
Por enquanto, vamos manter do jeito em que está mesmo. Para utilizar uma query em SQL, temos que verificar as opções que o framework entrega pra gente (se é anti SQL Injection e tudo mais).
Para essa thread, só basta a resolução do problema reportado que é o mesmo do filter_classes_by_schedule
. Valeu!
def filter_classes_by_schedule(schedule: str, classes: BaseManager[Class] = Class.objects) -> QuerySet: | ||
"""Filtra as turmas pelo horário.""" | ||
return classes.filter(schedule__icontains=schedule) |
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.
A proposta por realizar um filtro através do horário é boa, mas acho que não é eficiente utilizando essa função. Pelo o que eu entendi, ela vai encontrar padrões que contém trechos diretos. Por exemplo:
Imagine que temos uma lista de matérias distintas, com os seguintes horários:
schedules = ['24M34', '46M34']
Se eu realizo uma query para receber matérias que possuem o horário 4M34
, receberei apenas a primeira matéria, sendo que a segunda também possui o mesmo padrão.
Essa pesquisa é funcional, mas se limita a uma substring
de horário.
EDIT: A função icontains é equivalente:
SELECT classes WHERE schedule ILIKE '%4M34%';
Se a query fosse desse tipo (abaixo), o problema seria resolvido:
SELECT classes WHERE schedule ILIKE '%4%M%3%4%';
Ou seja: Com a query 4M34
, pode ter qualquer coisa antes do primeiro 4
e depois também. Logo após isso, vem o M
e também pode ter qualquer coisa entre o 3
e 4
.
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.
Excelente observação, Caio! Concordo com as sugestões e irei modificar o código para implementá-las.
return response.Response(data[:MAXIMUM_RETURNED_DISCIPLINES], status.HTTP_200_OK) | ||
|
||
|
||
class YearPeriod(APIView): | ||
|
||
@swagger_auto_schema( | ||
@ swagger_auto_schema( |
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.
Não utilizamos esse padrão de separação de decorators.
Descrição
closes #209
Foi implementado um filtro extra de pesquisa de disciplinas baseado no horário de aula desejado pelo usuário e o departamento que deseja encontrar uma turma. O usuário pode passar os seguintes parâmetros:
É importante notar o seguinte:
Tipo de alteração
Como isso foi testado?
A funcionalidade foi implementada utilizando a metodologia TDD, logo cada funcionalidade implementada está coberta por testes.
Checklist