如何在django rest framework serializer中获取父对象

时间:2015-01-08 23:02:32

标签: django django-rest-framework

我有这个模型

class Track(models.Model):
    album = models.ForeignKey(Album)

现在我的TrackSerializer我希望得到专辑的名称。

class TrackSerializer(serializers.ModelSerializer):

    class Meta:
        model = Track
        fields = ('album__name')

它不起作用

我不想为此声明AlbumSerializer。有没有办法做到这一点,而无需转发新的序列化程序

5 个答案:

答案 0 :(得分:11)

您可以在TrackSerializer上创建一个检索相册名称has a custom source的字段来执行此操作。

  

将用于填充字段的属性的名称。可能是一个只接受自我参数的方法,例如URLField(' get_absolute_url'),或者可以使用虚线表示法来遍历属性,例如EmailField(source =' user.email' )。

因此,在您的情况下,您的字段需要添加(在这种情况下为album_name)并使用自定义source

class TrackSerializer(serializers.ModelSerializer):
    album_name = serializers.CharField(read_only=True, source="album.name")

    class Meta:
        model = Track
        fields = ('album_name", )

这将在键album_name下的输出中包含相册名称。

答案 1 :(得分:4)

要包含父关系,您只需包含其序列化程序并将其包含在字段列表中即可。

Class TrackSerializer(ModelSerializer):
    album = AlbumSerializer()

    class Meta:
         model = Track
         fields = ('name', 'year', 'album',)

答案 2 :(得分:1)

我想为我的Django 2.0项目创建一个可浏览的api,该项目允许api用户使用超链接向下钻取到子项,然后再返回,甚至从子项开始并找到父项或祖父母通过超链接。另外,我不想使用pk数字,而是想使用一个从属字段来查找关系。

我找不到我想要做的任何完整的解决方案,只是点点滴滴,但是我终于能够将一个有效的api放在一起。我希望有人能找到扩展“专辑-曲目”示例的解决方案,有用。

对于所有代码,我深表歉意,但是通过复制和粘贴,您应该可以编写一个有效的示例。

这是我的models.py文件中的内容。请注意ForeignKey字段中的“ related_name”参数。使整个设置正常工作非常重要。

#models.py
class Artist(models.Model):
    name = models.CharField(max_length=100, blank=False)
    slug = models.SlugField(unique=True, blank=False)

class Album(models.Model):
    artist = models.ForeignKey(Artist, blank=False, 
                    on_delete=models.SET_DEFAULT, 
                    default=1, related_name='albums')
    name = models.CharField(max_length=100, blank=False)
    year = models.IntegerField()
    slug = models.SlugField(unique=True, blank=False)

class Track(models.Model):
    artist = models.ForeignKey(Artist, blank=False, 
                     on_delete=models.SET_DEFAULT, default=1, 
                     related_name='artist_tracks')
    album = models.ForeignKey(Album, blank=True, null=True,  
                     on_delete=models.SET_NULL, 
                     related_name='album_tracks')
    name = models.CharField(max_length=100)
    year = models.IntegerField()

下面是serializers.py。这是我在错误Could not resolve URL for hyperlinked relationship using view name "artist-detail". You may have failed to include the related model in your API, or incorrectly configured the 'lookup_field' attribute on this field.上最费力的地方。解决孩子问题很容易,并且模型也很方便。获取父母的url的关键在于queryset序列化程序的HyperlinkRelatedField参数和lookup_field= 'slug'。下面是我的序列化程序类。

#serializers.py
class ArtistSerializer(serializers.HyperlinkedModelSerializer):
    albums = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='album-detail',
        lookup_field='slug')
    class Meta:
        model = Artist
        fields = ('url', 'name', 'slug', 'albums') #, 'artist_tracks'
        lookup_field = 'slug',
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }

class AlbumSerializer(serializers.HyperlinkedModelSerializer):
    artist = serializers.HyperlinkedRelatedField(
        queryset=Artist.objects.all(),
        lookup_field='slug',
        view_name='artist-detail'
    )
    album_tracks = serializers.HyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='track-detail'
    )
    class Meta:
        model = Album
        fields = ('url', 'name', 'artist', 'album_tracks')
        lookup_field = 'slug',
        extra_kwargs = {
            'url': {'lookup_field': 'slug'}
        }

class TrackSerializer(serializers.HyperlinkedModelSerializer):
    artist = serializers.HyperlinkedRelatedField(
        queryset=Artist.objects.all(),
        lookup_field='slug',
        view_name='artist-detail'
    )
    album = serializers.HyperlinkedRelatedField(
        queryset=Album.objects.all(),
        lookup_field='slug',
        view_name='album-detail'
    )
    class Meta:
        model = Track
        fields = ('url', 'name', 'artist', 'album')

这是我的urls.py的内容。

#urls.py
urlpatterns = [
    path('artist/', ArtistList.as_view(), name='artist-list'),
    path('artist/<slug:slug>/', ArtistDetail.as_view(), name='artist-detail'),
    path('album/', AlbumList.as_view(), name='album_list'),
    path('album/<slug:slug>/', AlbumDetail.as_view(), name='album-detail'),
    path('track/', TrackList.as_view(), name='track-list'),
    path('track/<int:pk>/', TrackDetail.as_view(), name='track-detail'),
]

下一个views.py。请注意lookup_field='slug'类中的...Detail(RetrieveUpdateDestroyAPIView):

class ArtistList(ListCreateAPIView):
    queryset = Artist.objects.all()
    serializer_class = ArtistSerializer

class ArtistDetail(RetrieveUpdateDestroyAPIView):
    queryset = Artist.objects.all()
    serializer_class = ArtistSerializer
    lookup_field = 'slug'

class AlbumList(ListCreateAPIView):
    queryset = Album.objects.all()
    serializer_class = AlbumSerializer

class AlbumDetail(RetrieveUpdateDestroyAPIView):
    queryset = Album.objects.all()
    serializer_class = AlbumSerializer
    lookup_field = 'slug'

class TrackList(ListCreateAPIView):
    queryset = Track.objects.all()
    serializer_class = TrackSerializer

class TrackDetail(RetrieveUpdateDestroyAPIView):
    queryset = Track.objects.all()
    serializer_class = TrackSerializer

使用这种方法,我能够为曲目创建以下JSON,从中可以找到相关的艺术家和专辑:

{
"url": "http://127.0.0.1:8000/api/track/4/",
"name": "Lifeline",
"artist": "http://127.0.0.1:8000/api/artist/neal-morse/",
"album": "http://127.0.0.1:8000/api/album/lifeline/"
}

对于专辑,我能够生成如下所示的JSON,从而可以查找艺术家和专辑的所有曲目。

{
"url": "http://127.0.0.1:8000/api/album/lifeline/",
"name": "Lifeline",
"artist": "http://127.0.0.1:8000/api/artist/neal-morse/",
"album_tracks": [
    "http://127.0.0.1:8000/api/track/4/",
    "http://127.0.0.1:8000/api/track/5/",
    "http://127.0.0.1:8000/api/track/6/"
]
}

答案 3 :(得分:0)

你可以这样做(利用Python动态):

def create_serializer(target_class, fields):
    class ModelSerializer(serializers.ModelSerializer):

        class Meta:
            model = target_class
            fields = fields

    return ModelSerializer

因此,可以使用这种方法创建Track序列化器:

TrackSerializer = create_serializer(Track, ('album__name',))

另外,请注意(&#39; album__name&#39;),这是一个带括号的字符串表达式,而不是您想要的tuple。要将它声明为元组,请在其后添加逗号,如下所示:

fields = ('album__name',)

答案 4 :(得分:-3)

看起来你需要Serializer relations

它似乎也出现了一个非常类似的问题:django rest framework view does'nt show related table data