Django REST框架:嵌套关系:非字段错误

6 投票
2 回答
2552 浏览
提问于 2025-04-18 14:56

在一个Django-REST-framework项目中,我尝试使用嵌套关系,但在可浏览的API网页视图中遇到了“non_field_errors”的错误。

这段代码来自文档的这一部分:http://www.django-rest-framework.org/api-guide/relations#nested-relationships

models.py:

from django.db import models

class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks')
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    #duration = models.IntegerField()

    class Meta:
        unique_together = ('album', 'order')
        ordering = ('order',)

    def __unicode__(self):
        return '%d: %s' % (self.order, self.title)

serializers.py:

from rest_framework import serializers
from myapp.models import Album, Track

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('order', 'title')

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

错误信息(在../albums处):

轨道输入字段被标记为红色,错误信息是:non_field_errors。

点击OPTIONS按钮可以看到实际的、正确的数据结构:

轨道与它们相应的属性嵌套在一起。

可浏览的浏览器视图显示的原始数据输入是:

{
    "album_name": "", 
    "artist": "", 
    "tracks": null
}

发送一些有效的原始数据实际上是可以工作的。但如果网页界面的表单也能正常工作就更好了。特别是我在想,是否有什么奇怪的事情发生。

提前谢谢你!

2 个回答

0

一种解决办法就是在浏览器端把HTML表单隐藏起来。比如,你可以覆盖Rest Framework的api.html模板(通过创建你的应用文件夹下的templates/rest_framework/api.html),然后加上以下内容:

{% extends "rest_framework/base.html" %}

...

{% block script %}
{{ block.super }}
    <script>
    $('.form-switcher a[name="html-tab"]').hide();
    $('.form-switcher a[name="raw-tab"]').tab('show')
</script>
{% endblock %}

如果你想保留平坦的端点上的HTML表单,但想在嵌套的端点上去掉它,可以使用名称变量来作为标识。比如,在嵌套端点的名称中加入“Nested”,然后做类似这样的事情:

if("{{ name }}".indexOf("Nested") >= 0){
    $('.form-switcher a[name="html-tab"]').hide();
    $('.form-switcher a[name="raw-tab"]').tab('show').hide();
}
3

我也遇到过这个问题。解决这个错误的一种方法是使用:

class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.RelatedField(many=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

不过,这样做会去掉嵌套的轨道字段,只显示轨道的字符串表示。

补充一下:我找到了正确的方法。你需要的是这个:

class AlbumSerializer(serializers.ModelSerializer):

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')
        read_only_fields = ('tracks',)
        depth = 1

这样做可以让轨道嵌套,而不会出现界面错误。

撰写回答