【问题标题】:Django Serializers with Foreign Key not working带有外键的 Django 序列化程序不起作用
【发布时间】:2019-03-21 08:40:02
【问题描述】:

我想为我的模型创建一个 ListCreateView。 这是模型 -

from django.db import models

from training_service.models.advertiser import Advertiser

class Config(models.Model):
    CONFIG_TYPE_CHOICES = (
        ('DATA_DESCRIPTOR', 'DATA_DESCRIPTOR'),
        ('DATAFETCH', 'DATAFETCH'),
        ('BATCHSYSTEM', 'BATCHSYSTEM'),
        ('SPARKSYSTEM', 'SPARKSYSTEM')
    )

    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    config_type = models.CharField(max_length=100,
                                   choices=CONFIG_TYPE_CHOICES,
                                   blank=False)
    default_value = models.CharField(max_length=1000)

    class Meta:
        db_table = 'config'

    def __unicode__(self):
        return str(self.name)

class AdvertiserConfig(models.Model):
    advertiser_id = models.ForeignKey(
        Advertiser, to_field="advertiser_id", db_column="advertiser_id", on_delete=models.DO_NOTHING)
    config_id = models.ForeignKey(Config, on_delete=models.CASCADE)
    value = models.CharField(max_length=1000)

    class Meta:
        db_table = 'advertiser_config'

    def __unicode__(self):
        return str(self.name)

以下是模型的序列化程序 -

class ConfigSerializer(serializers.ModelSerializer):
    class Meta:
        model = Config
        fields = ('name', 'config_type', 'value_type', 'default_value')

class AdvertiserConfigSerializer(serializers.ModelSerializer):
    config_name = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
    class Meta:
        model = AdvertiserConfig
        fields = ('advertiser_id', 'config_name', 'value')

但是当我在 AdvertiserConfig 上执行 get 时,这不起作用我没有在响应中获得 config_name。并且不会抛出任何错误。

知道这里有什么问题吗? 另外,我将如何为 AdvertiserConfig 创建?

【问题讨论】:

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


    【解决方案1】:

    我不知道你为什么需要在这里使用PrimaryKeyRelatedField,你可以这样做:

    class AdvertiserConfigSerializer(serializers.ModelSerializer):
        class Meta:
            model = AdvertiserConfig
            fields = ('advertiser_id', 'config_id', 'value')
    

    如果你只想要一个带有 config_name 的字段,那么你可以使用SerializerMethodField:

    class AdvertiserConfigSerializer(serializers.ModelSerializer):
        config_name = serializers.SerializerMethodField()
        class Meta:
            model = AdvertiserConfig
            fields = ('advertiser_id', 'config_name', 'value')
    
        def get_config_name(self, obj):
             return obj.config_id.name  # will return config_id's name
    

    另外,请考虑重命名模型的 FK。因为当您使用名称为 config 的 ForignKey 时,django 会在 DB 中创建一个名称为 config_id 的列,该列指向 Config Model。

    【讨论】:

    • 谢谢。这解决了上市的问题。但它仍然不适用于创建新的广告客户配置。我尝试重写 create 函数,但它没有 config_name 作为validated_data 字典的一部分。 ://
    • SerializerMethodFIeld 是只读方法。因此,当您发出 GET 请求时,您将看到该值。但是如果你想写值,那么你就使用第一个解决方案。在那里您需要输入config_id 的值,这是配置模型的PK。但是如果你想使用config_id作为读写值name,那么你需要使用SlugRelatedField。但是您需要确保name 的值是唯一的
    【解决方案2】:

    如果你只想要配置的名称,你可以使用 SlugRelatedField

    class AdvertiserConfigSerializer(serializers.ModelSerializer):
    config = serializers.SlugRelatedField(slug_field='name', read_only=True, many=True)
    class Meta:
        model = AdvertiserConfig
        fields = ('advertiser_id', 'config', 'value')
    

    并按照 ruddras 提示重命名您的模型 FK。

    【讨论】:

    • 这对我不起作用。在这里发布之前我已经尝试过了。
    • 我发现了 SlugRelatedField 的问题。我 config_name 没有唯一的约束。现在它适用于 GET 请求。谢谢你。但它仍然不适用于 POST 创建/更新条目。
    • 对于有效的 POST 请求,您必须像 config = AdvertiserConfigSerializer(many=True) 一样使用它并覆盖 save 方法来保存两个模型。但是你不会只获取 config.name 而是获取配置数据。
    猜你喜欢
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多