我有这个模型
class Track(models.Model):
album = models.ForeignKey(Album)
现在我的TrackSerializer
我希望得到专辑的名称。
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('album__name')
它不起作用
我不想为此声明AlbumSerializer。有没有办法做到这一点,而无需转发新的序列化程序
答案 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