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

时间:2018-01-21 00:08:42

标签: django django-rest-framework

初步说明:这是一个相当新手的问题,虽然我没有在StackOverflow上找到足够的答案;许多类似的问题,但不是这个问题。所以我问了一个新问题。

问题:我在创建记录时遇到困难,其中一个字段是现有记录的外键,我不知道我在代码中做错了什么。

在我的应用中,有两个模型,公司和BalanceSheet之间的一对多关系:

模型:

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 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 BalanceSheetCreate(generics.CreateAPIView):
    model = BalanceSheet
    queryset = BalanceSheet.objects.all()
    serializer_class = BalanceSheetSerializer

网址包括:

url(r'^(?P<symbol>[A-Z]{1,4})/create-balance-sheet/$', views.BalanceSheetCreate.as_view(),
        name='create_balance_sheet'),

到目前为止,我没有读取数据的问题。但是,在尝试创建记录时,我会收到错误,我不明白:

curl http://localhost:8000/financials/AAPL/create-balance-sheet/ -X POST -d "company=AAPL&date=1968-04-17&profit=1&loss=1"
IntegrityError at /financials/AAPL/create-balance-sheet/
null value in column "company_id" violates not-null constraint

从该curl命令中删除公司数据会导致相同的错误。

如何解决此错误?我以为我是在告诉api我对我感兴趣的公司,在网址和帖子数据中明确表示。

使用python3.6,django 1.11和djangorestframework 3.7.7

2 个答案:

答案 0 :(得分:1)

您获得了IntegrityError,因为您的代码会尝试在没有公司的情况下创建新的BalanceSheet。这是因为StringRelatedField是只读的(请参阅docs),因此在写入模式下使用BalanceSheetSerializer时,它不会被解析。

您需要

SlugRelatedField

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

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

答案 1 :(得分:0)

回答我自己的问题,这就是我最后的问题。再次感谢前往dukebody。

模型:

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 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

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