Django REST Serializer постоянно изменяется в init
Я столкнулся со странной проблемой с DRF: у меня есть несколько сериализаторов, для которых я хочу отображать определенные поля только при определенных условиях, таких как наличие url-параметров в запросе или наличие у пользователя определенных прав.
Чтобы отделить логику представления моего сериализатора от бизнес-логики, я решил добавить атрибут conditional_fields
к классу сериализатора Meta
: это dict, в котором ключи - строки, представляющие условия, например "SHOW_HIDDEN_FIELDS"
, а их значения - списки имен полей, которые нужно удалить, если ключ не присутствует в сериализаторе context
. Затем я переопределяю метод get_serializer_context
моего набора представлений, чтобы получить нужные значения внутри контекста.
Я создал метод remove_unsatisfied_condition_fields
, который делает следующее:
def remove_unsatisfied_condition_fields(self):
conditional_fields = self.Meta.conditional_fields
for condition, fields in conditional_fields.items():
if not self.context.get(condition, False):
for field in fields:
self.fields.pop(field, None)
Сериализаторы, использующие его, выглядят следующим образом:
class ExerciseSerializer(serializers.ModelSerializer):
class Meta:
model = Exercise
fields = [
"id",
"text",
"solution",
"correct_choices"
]
conditional_fields = {
"EXERCISE_SHOW_HIDDEN_FIELDS": ["solution", "correct_choices"],
}
Здесь возникает проблема: если я вручную вызываю этот метод внутри моих сериализаторов, в их методе __init__
, вот так:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.remove_unsatisfied_condition_fields()
все работает нормально.
Однако, если я сделаю их наследуемыми от класса, который делает это автоматически, например, так:
class ConditionalFieldsMixin:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.remove_unsatisfied_condition_fields()
def remove_unsatisfied_condition_fields(self):
conditional_fields = self.Meta.conditional_fields
for condition, fields in conditional_fields.items():
if not self.context.get(condition, False):
for field in fields:
self.fields.pop(field, None)
и заставить мои сериализаторы наследоваться от него, происходит следующее:
как только приходит запрос, который не удовлетворяет одному из условий сериализатора conditional_fields
, поле, кажется, "навсегда" удаляется из сериализатора: все последующие запросы, которые включают его, даже если они приводят к появлению context
с надлежащими условиями для отображения этого поля, отвечают без этого поля. Как будто сериализатор перестает иметь это поле навсегда - только переразвертывание моего приложения заставляет его вернуться.
Это очень странно, и я понятия не имею, почему это происходит, только если удаление выполняется внутри класса в цепочке наследования сериализатора, а не в самом сериализаторе.
Связано ли это с каким-то странным правилом наследования Pythonic, о котором я не знаю, или я что-то упустил в сериализаторах?