Django Rest Framework - 将序列化程序字段映射到数据库列名

时间:2015-09-28 19:52:00

标签: django django-models django-rest-framework

我正在处理Django Rest Framework项目,我的视图的通用响应不是应用程序客户期望的。

应用客户端期望相关模型的字段显示为数据库中的字段。给出的示例:model City具有Country模型的外键,由country_id列表示。

是否可以选择" map"序列化程序默认字段为自定义字段?我查看了Django Rest Framework文档,但我只找到" serializer_field_mapping"但我不知道它是否符合我的要求,而且我也不知道如何使用它。

不知怎的,我得到了一个接近的方法,但只是在获取数据的情况下 - 创建/更新抛出了一些我没有得到如何管理的错误。 :(

Bellow我附上了models.py文件,加上实际输出和所需的输出。此外,如果可能,我想检索与国家/地区相关的数据(如果存在)与数据库列 field_id 名称相结合。

提前致谢,

models.py

from django.db import models
from django.contrib.postgres.fields import ArrayField


class Country(models.Model):

    name = models.CharField(max_length=150, unique=True, blank=False)

    class Meta:
        db_table = 'countries'


class Region(models.Model):

    name = models.CharField(max_length=150, unique=True, blank=False)
    code = models.CharField(max_length=150, blank=True)

    class Meta:
        db_table = 'regions'


class City(models.Model):

    country = models.ForeignKey(Country)
    region = models.ForeignKey(Region, null=True, blank=True, default=None)
    name = models.CharField(max_length=150, unique=True, blank=False)
    postal_codes = ArrayField(models.CharField(max_length=12, blank=True), null=True, blank=True, default=None)

    def __str__(self):
        if not self.region:
            return '%s (%s)' % (self.name, self.country.name)
        return '%s, %s (%s)' % (self.name, self.region.name, self.country.name)

    class Meta:
        db_table = 'cities'

实际输出:

[
  {
    "id": 1,
    "name": "San Francisco",
    "postal_codes": null,
    "country": 1,
    "region": 1
  },
  {
    "id": 2,
    "name": "Palo Alto",
    "postal_codes": null,
    "country": 1,
    "region": 1
  },
  {
    "id": 3,
    "name": "New York City",
    "postal_codes": null,
    "country": 1,
    "region": 2
  },
  {
    "id": 4,
    "name": "London",
    "postal_codes": null,
    "country": 2,
    "region": null
  }
]

期望输出:

[
  {
    "id": 1,
    "country_id": 1,
    "region_id": 1,
    "name": "San Francisco",
    "postal_codes": null
  },
  {
    "id": 2,
    "country_id": 1,
    "region_id": 1,
    "name": "Palo Alto",
    "postal_codes": null
  },
  {
    "id": 3,
    "country_id": 1,
    "region_id": 2,
    "name": "New York City",
    "postal_codes": null
  },
  {
    "id": 4,
    "country_id": 2,
    "region_id": null,
    "name": "London",
    "postal_codes": null
  }
]

2 个答案:

答案 0 :(得分:5)

您可以使用序列化程序中字段的source参数来实现此目的。例如:

from rest_framework import serializers

from .models import City


class CitySerializer(serializers.ModelSerializer):
    country_id = serializers.IntegerField(source='country')
    region_id = serializers.IntegerField(source='region')

    class Meta:
        model = City
        fields = ('id', 'country_id', 'region_id', 'name', 'postal_codes')

编辑:正如雅罗斯拉夫所指出的那样,当你这样做时,你不需要包含source。但请注意,仅在country_id列表中包含region_idfields是不够的。您仍需要在序列化程序中指定字段,例如country_id = serializers.IntegerField(),并将其包含在fields中。

答案 1 :(得分:4)

感谢所有人。终于我明白了。见下面的代码。我回答我的问题,因为没有选项可以在答案评论上添加大量的行。

<强> serializers.py

from rest_framework import serializers
from .models import Country, Region, City


class CountrySerializer(serializers.ModelSerializer):

    class Meta:
        model = Country
        fields = ('id', 'name')


class RegionSerializer(serializers.ModelSerializer):

    class Meta:
        model = Region
        fields = ('id', 'name', 'code')


class CitySerializer(serializers.ModelSerializer):

    country_id = serializers.PrimaryKeyRelatedField(
        queryset=Country.objects.all(),
        required=True,
        source='country',
    )
    region_id = serializers.PrimaryKeyRelatedField(
        queryset=Region.objects.all(),
        allow_null=True,
        required=False,
        source='region',
    )

    country = CountrySerializer(
        read_only=False,
        required=False,
    )
    region = RegionSerializer(
        required=False,
        allow_null=True,
        read_only=True,
    )

    class Meta:
        model = City
        fields = (
            'id',
            'country', 'region',
            'name', 'postal_codes',
            'country_id', 'region_id',
        )