目的
Pinterestのようにユーザー毎にフォルダを作成できて、ファイルをアップロードして他ユーザーと共有し、他ユーザーがアップしたファイルを自分のフォルダにも保存できるようなサービスを開発しています。
上記を実現するために、掲題のような処理を書いてみました、
ソース
# 1.コピー
# コピー元のレコードを取得
fileObj = file.objects.filter(id=id)
# querysetをdictに変換
fileJson = list(fileObj.values())[0]
# 2.更新
fileJson.pop('user_id')
fileJson.pop('folder_id')
fileJson.user = user
fileJson.folder = folder
# 3.新規登録
serializer = FileSerializer(data=fileJson)
if serializer.is_valid():
# エラー処理
Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializer.save()
return Response(status=status.HTTP_201_CREATED)
補足
コピー
- 一番時間がかかってしまったところ
-
queryset json 変換
とかで検索すると、下記のようなコードが出てくるが求めていたものと違っていた
# serializerで返ってくるやん
json_encode = serializers.serialize('json', WorkList, ensure_ascii=False)
# 文字列で返ってくるやん
json_encode = json.dumps(list(WorkList), cls=DjangoJSONEncoder)
更新
-
models.ForeignKey
でユーザーテーブルなど外部参照している場合は、参照先のデータが入れ子になって取得される。新規登録時はIDのみでいいので、取得したデータを削除して入れ直している。
新規登録
- あとは、通常のレコード作成と同様にSerializerでバリデーションをかけてsaveして終わり
追記
- こんな感じでも実現できた
ソース
# 更新するデータのみのシリアライザーを用意
serializer = FileCopySerializer(data=request.data)
# バリデーション
if serializer.is_valid():
# エラー処理
Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# コピー元のレコードを取得
fileObj = file.objects.filter(id=serializer.validated_data.get('id'))
# 更新
# idをNoneにすることで新規登録できる
fileObj.id = None
fileObj.user = serializer.validated_data.get('user')
fileObj.folder = serializer.validated_data.get('folder')
# modelに新規登録のインスタンスメソッドを定義して呼び出し
fileObj.save()
return Response(status=status.HTTP_201_CREATED)
- コピー用のSerializerを用意したり、modelに新規登録のインスタンスメソッドを用意したりと、こちらの方がコード量が多い
- 前半に紹介したコードだと、serializerで更新対象外なデータのバリデーションも行っているので、わずかながらこちらの方が処理が早いかも