Django REST框架,处理创建记录的相关字段

Django REST框架,处理创建记录的相关字段,django,django-rest-framework,Django,Django Rest Framework,初步说明:这是一个相当新的问题,尽管我还没有找到关于StackOverflow的充分答案;很多类似的问题,但不是这个。所以我要问一个新问题 问题是:当一个字段是现有记录的外键时,我很难创建记录,并且我不知道我在代码中犯了什么错误 在我的应用程序中,有两种模型存在疑问,即公司与资产负债表之间的一对多关系: 型号: class Company(models.Model): cik = models.IntegerField(default=0, unique=True) symbol

初步说明:这是一个相当新的问题,尽管我还没有找到关于StackOverflow的充分答案;很多类似的问题,但不是这个。所以我要问一个新问题

问题是:当一个字段是现有记录的外键时,我很难创建记录,并且我不知道我在代码中犯了什么错误

在我的应用程序中,有两种模型存在疑问,即公司与资产负债表之间的一对多关系:

型号:

class Company(models.Model):
    cik = models.IntegerField(default=0, unique=True)
    symbol = models.CharField(max_length=4, unique=True)
    name = models.CharField(max_length=255, unique=True)

    def __str__(self):
        return self.symbol

class BalanceSheet(models.Model):
    company = models.ForeignKey(Company,
        null=True,
        on_delete=models.CASCADE,
        related_name='balance_sheets',)
    date = models.DateField()
    profit = models.BigIntegerField()
    loss = models.BigIntegerField()

    class Meta:
        unique_together = (('company', 'date'),)

    def __str__(self):
        return '%s - %s' % (self.company, self.date)
class Company(models.Model):
    cik = models.IntegerField(default=0)
    symbol = models.CharField(max_length=4)
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.symbol


class BalanceSheet(models.Model):
    company = models.ForeignKey(Company,
        null=True,
        on_delete=models.CASCADE,
        related_name='balance_sheets',)
    date = models.DateField()
    profit = models.BigIntegerField()
    loss = models.BigIntegerField()

    class Meta:
        unique_together = (('company', 'date'),)

    def __str__(self):
        return '%s - %s' % (self.company, self.date)
序列化程序:

class BalanceSheetSerializer(serializers.ModelSerializer):
    company = serializers.StringRelatedField()

    class Meta:
        model = BalanceSheet
        fields = ('company','date','profit','loss')


class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('cik', 'symbol', 'name')
class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('cik', 'symbol', 'name')


class BalanceSheetSerializer(serializers.ModelSerializer):
    company = CompanySerializer(many=False)

    class Meta:
        model = BalanceSheet
        fields = ('company', 'date', 'profit', 'loss')

    def create(self, validated_data):
        company_data = validated_data['company']
        company, created = Company.objects.get_or_create(**company_data)
        validated_data['company'] = company
        sheet = BalanceSheet.objects.create(**validated_data)
        return sheet
观点:

class BalanceSheetCreate(generics.CreateAPIView):
    model = BalanceSheet
    queryset = BalanceSheet.objects.all()
    serializer_class = BalanceSheetSerializer
URL包括:

url(r'^(?P<symbol>[A-Z]{1,4})/create-balance-sheet/$', views.BalanceSheetCreate.as_view(),
        name='create_balance_sheet'),
从该curl命令中删除公司数据会导致相同的错误

我如何避免这个错误?我想我是在告诉api我感兴趣的公司,无论是在url还是在post数据中


使用python3.6、django 1.11和djangorestframework 3.7.7

您将获得
IntegrityError
,因为您的代码将尝试在没有公司的情况下创建新的
资产负债表。这是因为
StringRelatedField
是只读的(请参阅),因此在写入模式下使用
BalanceSheetSerializer
时不会对其进行分析

您需要的是:

class BalanceSheetSerializer(serializers.ModelSerializer):
    company = serializers.SlugRelatedField(slug_field='symbol')

    class Meta:
        model = BalanceSheet
        fields = ('company','date','profit','loss')

回答我自己的问题,以下是我的结论。再次感谢你去dukebody

型号:

class Company(models.Model):
    cik = models.IntegerField(default=0, unique=True)
    symbol = models.CharField(max_length=4, unique=True)
    name = models.CharField(max_length=255, unique=True)

    def __str__(self):
        return self.symbol

class BalanceSheet(models.Model):
    company = models.ForeignKey(Company,
        null=True,
        on_delete=models.CASCADE,
        related_name='balance_sheets',)
    date = models.DateField()
    profit = models.BigIntegerField()
    loss = models.BigIntegerField()

    class Meta:
        unique_together = (('company', 'date'),)

    def __str__(self):
        return '%s - %s' % (self.company, self.date)
class Company(models.Model):
    cik = models.IntegerField(default=0)
    symbol = models.CharField(max_length=4)
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.symbol


class BalanceSheet(models.Model):
    company = models.ForeignKey(Company,
        null=True,
        on_delete=models.CASCADE,
        related_name='balance_sheets',)
    date = models.DateField()
    profit = models.BigIntegerField()
    loss = models.BigIntegerField()

    class Meta:
        unique_together = (('company', 'date'),)

    def __str__(self):
        return '%s - %s' % (self.company, self.date)
序列化程序:

class BalanceSheetSerializer(serializers.ModelSerializer):
    company = serializers.StringRelatedField()

    class Meta:
        model = BalanceSheet
        fields = ('company','date','profit','loss')


class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('cik', 'symbol', 'name')
class CompanySerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = ('cik', 'symbol', 'name')


class BalanceSheetSerializer(serializers.ModelSerializer):
    company = CompanySerializer(many=False)

    class Meta:
        model = BalanceSheet
        fields = ('company', 'date', 'profit', 'loss')

    def create(self, validated_data):
        company_data = validated_data['company']
        company, created = Company.objects.get_or_create(**company_data)
        validated_data['company'] = company
        sheet = BalanceSheet.objects.create(**validated_data)
        return sheet

我还必须将完整的公司数据作为嵌套dict包含在curl语句中。

外键确实需要
null=true
吗?不幸的是,切换该值不会改变任何结果。谢谢。这真的很有帮助,尽管我现在遇到了queryset问题。除了官方文档之外,您还知道编写API的资源吗?官方文件似乎是面向阅读的,在当时似乎已经过时了。(请参阅“检查关系”中的Python2样式打印语句)我不知道,如果您进行web搜索,有很多资源和教程。。。如果您有特定问题或不了解的内容,请将其发布到,以便人们能够帮助您。:)