LoginSignup
2
1

More than 1 year has passed since last update.

【Django】特定のレコードをコピー・更新して、新規登録したい

Last updated at Posted at 2021-08-18

目的

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で更新対象外なデータのバリデーションも行っているので、わずかながらこちらの方が処理が早いかも
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1