我有以下两个序列化器:
class RankingVC: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionViewDelegates()
registerCells()
view.backgroundColor = .red
}
}
extension RankingVC : UICollectionViewDelegate, UICollectionViewDataSource {
func setupCollectionViewDelegates() {
collectionView.delegate = self
collectionView.dataSource = self
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellIdentifier.rankingCVCell, for: indexPath) as! RankingCVCell
return cell
}
func registerCells() {
RegisterCVCells.registerCell(withNibName: CellIdentifier.rankingCVCell, forCollectionView: collectionView)
}
}
它们基于以下模型:
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
from radio.models import Program
model = Program
fields = ('id', 'title')
class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
program_data = ProgramSerializer(read_only=True)
class Meta:
model = UserRecentlyPlayed
fields = ('id', 'user', 'program', 'program_data',)
我要执行的操作如下:在创建时,我希望能够通过以下方式创建UserRecentlyPlayed的新实例:
class Program(models.Model):
title = models.CharField(max_length=64)
class UserRecentlyPlayed(models.Model):
user = models.ForeignKey(User)
program = models.ForeignKey(Program)
但是,当我返回列表时,我想返回以下内容:
{
"user": "...user id ....",
"program": "....program id...."
}
这些在以下视图中被调用:
[{
"id": "... id .... ",
"user": ".... user id .....",
"program": {"id": "...program id...", "title": "...title..." }
}]
不幸的是,这不起作用。正确的魔术是什么?
答案 0 :(得分:1)
您可以将序列化器中的program_data
重命名为program
,也可以为嵌套序列化器指定源。
那应该返回列表的输出。
class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
program = ProgramSerializer(read_only=True)
class Meta:
model = UserRecentlyPlayed
fields = ('id', 'user', 'program',)
或
class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
program_data = ProgramSerializer(read_only=True, source='program')
class Meta:
model = UserRecentlyPlayed
fields = ('id', 'user', 'program_data',)
要支持创建相同的json输入,最简单的方法是创建另一个序列化程序用于输入:
class UserRecentlyPlayedSerializerInput(serializers.ModelSerializer):
program = serializers.PrimaryKeyRelatedField(queryset=Program.objects.all())
class Meta:
model = UserRecentlyPlayed
fields = ('id', 'user', 'program',)
并在请求为POST / PUT / PATCH时在您的视图中使用它:
class RecentlyPlayed(generics.ListCreateAPIView):
serializer_class = UserRecentlyPlayedSerializer
def get_serializer_class(self):
if self.request.method.lower() == 'get':
return self.serializer_class
return UserRecentlyPlayedSerializerInput
虽然这很适合“获得”,但我希望看到同样的结果 创建后的结果。我仍然看到{“ program”:“ ... id ....”
为此,您必须在视图中稍微更改create方法的实现
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = serializer.save()
headers = self.get_success_headers(serializer.data)
oser = UserRecentlyPlayedSerializer(instance)
return Response(oser.data, status=status.HTTP_201_CREATED,
headers=headers)
答案 1 :(得分:0)
首先在模型中创建一个名为program_data
的属性
class Program(models.Model):
title = models.CharField(max_length=64)
class UserRecentlyPlayed(models.Model):
user = models.ForeignKey(User)
program = models.ForeignKey(Program)
@property
def program_data(self):
return self.program
然后在序列化程序中,您无需更改任何内容,它将保持与以下相同
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
from radio.models import Program
model = Program
fields = ('id', 'title')
class UserRecentlyPlayedSerializer(serializers.ModelSerializer):
program_data = ProgramSerializer(read_only=True)
class Meta:
model = UserRecentlyPlayed
fields = ('id', 'user', 'program', 'program_data',)
答案 2 :(得分:0)
好吧,我朝一个略有不同的方向走了,而且行得通。我没有使用ListCreateAPIView,而是使用ListModeMixin,CreateModelMixin和GenericAPIView创建了自己的类。魔术是覆盖def list类。我还实现了“ return_serializer_class”属性。就是这样。
class RecentlyPlayed(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
serializer_class = UserRecentlyPlayedSerializer
return_serializer_class = ProgramSerializer
parser_classes = (JSONParser, MultiPartParser)
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.create(request, *args, **kwargs)
return self.list(request, *args, **kwargs)
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.return_serializer_class(queryset, many=True)
return Response({'recently_played': serializer.data})