私はDjango REST Frameworkを使用しています
request.data = '{"id": "10", "user": "tom"}'
さらに「いいね」に送信する前に、"age": "30"
などの属性を追加したい
request.data = new_data
response = super().post(request, *args, **kwargs)
2つの問題があります
一般に、DRFビューのrequest
はrest_framework.request.Request
インスタンス。それに続くソースコード(djangorestframework==3.8.2
):
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
return self._full_data
できるよ:
request._full_data = your_data
良い友達が上に示したよりもずっと簡単なアプローチで私を学校に連れて行ってくれた
class CreateSomething(CreateAPIView):
model = Something
queryset = Something.objects.all()
serializer_class = SomethingSerializer
perform_create(self,serializer):
def perform_create(self,serializer):
ip = self.get_ip()
## magic here: add kwargs for extra fields to write to db
serializer.save(ip_addr=ip)
def get_ip(self):
x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR',None)
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = self.request.META.get('REMOTE_ADDR',None)
return ip
class SomethingSerializer(serializers.ModelSerializer):
email = serializers.EmailField(validators=[UniqueValidator(queryset=Something.objects.all())])
fieldA = serializers.CharField()
fieldB = serializers.CharField()
class Meta:
model = Customer2
fields = ['email','fieldA','fieldB','ip_addr']
read_only_fields = ['ip_addr']
Json文字列のように見えます。それを辞書に変換するには、次のようにします。
import json
data = json.loads(request.data)
次に、属性を追加できます。
data['age'] = 30
古いリクエストを変更することはできないので、新しいリクエストを行う必要があります。これは、/ notes /に投稿していることを前提としています。
from rest_framework.test import APIRequestFactory
factory = APIRequestFactory()
request = factory.post('/notes/', data, format='json')
APIがAPIView
の場合は、更新関数を使用して、クライアント側から送信されたデータを失うことなく要求データオブジェクトを拡張する必要があります。
request.data.update({"id": "10", "user": "tom"})
あなたのコメントによると:
「投稿する前に、APIで必要なフィールド名AQを変更する必要があるため」
代わりにField
の- source
引数 を使用する必要があります。
これにより、エラーメッセージの一貫性が向上します。そうしないと、ユーザーが提供していないフィールド名でエラーが発生します。
私はこれを別の方法で扱いました。 CreateAPIView createメソッドを次のようにオーバーライドします
class IPAnnotatedObject(CreateAPIView):
model = IPAnnotatedObject
queryset = IPAnnotatedObject.objects.all()
serializer_class = IPAnnotatedObject
def create(self, request, *args, **kwargs):
request.data['ip_addr'] = self.get_ip()
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
## perform_create calls serializer.save() which calls the serializer's create() method
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def get_ip(self):
x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR',None)
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = self.request.META.get('REMOTE_ADDR',None)
return ip
対応するシリアライザークラスは次のようになります。
class IPAnnotatedObjectSerializer(serializers.ModelSerializer):
email = serializers.EmailField(validators=[UniqueValidator(queryset=IPAnnotatedObject.objects.all())])
password = serializers.CharField(write_only=True)
ip_addr = serializers.IPAddressField(write_only=True)
class Meta:
model = IPAnnotatedObject
fields = ['email','password','created_ip']
def create(self, validated_data):
email, password, created_ip = validated_data['email'], validated_data['password'],validated_data['created_ip']
try:
ipAnnoObject = IPAnnotatedObject.objects.create(email=email,password=make_password(password),ip_addr=ip_addr)
except Exception as e:
# you can think of better error handler
pass
return ipAnnoOjbect
エンドポイントがDRF ViewSet
で実装されている場合、解決策は、対応するシリアライザクラスのto_internal_value
メソッドを実装し、そこでデータを変更することです。
class MyModelViewSet(viewsets.ModelViewSet):
authentication_classes = ...
...
serializer_class = MyModelSerializer
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'user', ...)
def to_internal_value(self, data):
instance = super(MyModelSerializer, self).to_internal_value(data)
if "lastModified" in data:
# instance["id"] = 10 # That's sketchy though
instance["user"] = "tom"
return instance