Я хочу сериализовать неровную структуру на один плоский объект. Вот пример вызова API, который я получаю (к сожалению, я не могу его контролировать):
{
"webhookEvent": "jira:issue_updated",
"user": {
"id": 2434,
"name": "Ben",
},
"issue": {
"id": "33062",
"key": "jira-project-key-111",
"fields": {
"summary": "The week ahead",
},
"changelog": {
"id": "219580",
"items": [{
"field": "status",
"fieldtype": "jira",
"from": "10127",
"fromString": "Submitted",
"to": "10128",
"toString": "Staged"
}]
},
"timestamp": 1423234723378
}
Я хотел бы сериализовать его для таких моделей, как:
class Issue(models.Model):
jira_id = models.IntegerField()
jira_id = models.CharField()
summary = models.CharField()
class Change(models.Model):
issue = models.ForeignKey(Issue)
timestamp = models.DataTimeField()
Как вы можете видеть, поле Issue
summary
находится на том же объекте, что и id
и key
, в отличие от данных JSON.
Мой Сериализатор следующий:
class ChangeSerializer(serializers.ModelSerializer):
"""Receives complex data from jira and converts into objects."""
issue = JiraIssueSerializer()
timestamp = TimestampField(source='created_at')
class Meta:
model = Change
fields = ('issue', 'timestamp')
def create(self, validated_data):
super(serializers.ModelSerializer, self).create(validated_data=validated_data)
jira_issue = JiraIssueSerializer(data=validated_data)
issue = Issue.objects.get(jira_issue)
self.created_at = datetime.utcnow()
change = Change(**validated_data)
return change
class JiraIssueSerializer(serializers.ModelSerializer):
"""Issue serializer."""
id = serializers.IntegerField(source='jira_id')
key = serializers.CharField(source='jira_key')
summary = serializers.CharField() ### I want field to work!
# fields = serializers.DictField(child=serializers.CharField())
class Meta:
model = Issue
fields = ('id', 'key',
'summary',
)
def to_internal_value(self, data):
# ret = super(serializers.ModelSerializer, self).to_internal_value(data)
ret = {}
# ret = super().to_internal_value(data)
ret['jira_id'] = data.get('id', None)
ret['jira_key'] = data.get('key', None)
jira_issue_fields_data = data.get('fields')
if jira_issue_fields_data or 1:
summary = jira_issue_fields_data.get('summary', None)
ret.update(summary=summary)
print('to_internal_value', ret)
return ret
def to_representation(self, instance):
ret = {}
ret = super().to_representation(instance)
fields = {}
fields['summary'] = instance.summary
ret.update(fields=fields)
print(ret)
return ret
Я хорошо работаю для полей в объекте Issue
в JSON.
Но как я могу добавить в JiraIssueSerializer некоторые поля, например summary
? Они не являются прямыми полями объекта Issue
, но расположены в substrcucture fields
.
Я вижу следующие способы:
-
Сделайте еще одну модель
fields
, чтобы сохранить их, но это смешно. Мне это не нужно, и мой API строго зависит от внешней структуры. -
Сделайте несколько преобразователей
.to_internal_fields()
. Но в этом случае я должен вручную проверить и подготовить все поля в моемIssue
и повторить несколько раз. Также если полеsummary
не зачислено в Сериализатор, последний не может его использовать или проверка не выполняется. -
Добавить
DictField
в Serializer (прокомментированный в коде) и взять данные из него. Это хорошо? Как проверить его? Опять же, у меня есть чистая структура кода.
Далее я хотел бы проанализировать и сохранить данные изменений.
Как лучше справляться с такими структурами?
Спасибо!