DRF:如何将额外的上下文数据传递给序列化程序
DRF: How to pass extra context data to serializers
我在网上搜索并找到了类似的 ,但它在我的情况下不起作用,我不知道为什么。
我尝试在序列化程序中将一些额外数据放入 context
,但只得到 3 个默认字段:request
、view
和 format
,没有提及我的自定义数据。
我的模特:
class Match(models.Model):
sender = models.ForeignKey(
Client,
on_delete=models.CASCADE,
related_name='senders'
)
recipient = models.ForeignKey(
Client,
on_delete=models.CASCADE,
related_name='recipients'
)
class Meta:
app_label = 'clients'
db_table = 'matches'
verbose_name = 'match'
verbose_name_plural = 'matches'
constraints = [
models.UniqueConstraint(
fields=['sender', 'recipient'],
name='unique_match'
)
]
我的序列化程序:
class MatchSerializer(serializers.ModelSerializer):
sender = serializers.HiddenField(default=serializers.CurrentUserDefault())
def validate(self, data):
if data['sender'] == self.context['recipient']:
raise serializers.ValidationError('You cannot match yourself')
return data
def create(self, validated_data):
return Match.objects.create(
sender=validated_data['sender'],
recipient=self.context['recipient']
)
class Meta:
model = Match
fields = ['sender']`
我的模型视图集:
class MatchMVS(ModelViewSet):
queryset = Match.objects.all()
serializer_class = MatchSerializer
http_method_names = ['post']
permission_classes = [IsAuthenticated]
# without and with doesn't work
def get_serializer_context(self):
context = super(MatchMVS, self).get_serializer_context()
context.update({
"recipient": Client.objects.get(pk=23)
# extra data
})
return context
@action(detail=True, methods=['POST'], name='send_your_match')
def match(self, request, pk=None):
sender = request.user
recipient = Client.objects.get(pk=pk)
serializer = MatchSerializer(context={'request': request, 'recipient': recipient},
data=request.data)
data_valid = serializer.is_valid(raise_exception=True)
if data_valid:
recipient = serializer.save()
is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
if is_match:
send_mail(
f'Hello, {sender.first_name}',
f'You got match with {recipient.first_name}! '
f'Your`s partner email: {recipient.email}',
settings.EMAIL_HOST_USER,
[sender.email],
fail_silently=False,
)
send_mail(
f'Hello, {recipient.first_name}',
f'You got match with {sender.first_name}! '
f'Your`s partner email: {sender.email}',
settings.EMAIL_HOST_USER,
[recipient.email],
fail_silently=False,
)
return Response(recipient.email, 201)
else:
return Response(f'Your sympathy has been sent to {recipient.username}.', 201)
我正在通过 PyCharm 和 Postman 进行调试,但仍然无法理解我的错误在哪里。希望你能帮我解决它。
您的代码 right.It 应该可以工作。但是我不知道在哪里 issue.You 可以试试下面修改后的代码。
class MatchSerializer(serializers.ModelSerializer):
def validate(self, data):
if data['sender'] == data['recipient']:
raise serializers.ValidationError('You cannot match yourself')
return data
class Meta:
model = Match
fields = ['sender', 'recipient']
class MatchMVS(ModelViewSet):
queryset = Match.objects.all()
serializer_class = MatchSerializer
http_method_names = ['post']
permission_classes = [IsAuthenticated]
@action(detail=True, methods=['POST'], name='send_your_match')
def match(self, request, pk=None):
sender = request.user
recipient = Client.objects.get(pk=pk)
serializer = MatchSerializer(data={**request.data, 'recipient': recipient.id})
data_valid = serializer.is_valid(raise_exception=True)
if data_valid:
recipient = serializer.save()
is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
if is_match:
send_mail(
f'Hello, {sender.first_name}',
f'You got match with {recipient.first_name}! '
f'Your`s partner email: {recipient.email}',
settings.EMAIL_HOST_USER,
[sender.email],
fail_silently=False,
)
send_mail(
f'Hello, {recipient.first_name}',
f'You got match with {sender.first_name}! '
f'Your`s partner email: {sender.email}',
settings.EMAIL_HOST_USER,
[recipient.email],
fail_silently=False,
)
return Response(recipient.email, 201)
else:
return Response(f'Your sympathy has been sent to {recipient.username}.', 201)
问题是我自己不注意,错误的viewset被链接到url
urlpatterns = [
path('clients/<int:pk>/match', views.MatchCreateAPIView.as_view(), name='get_match')
]
而不是:
urlpatterns = [
path('clients/<int:pk>/match', views.MatchMVS.as_view({'post': 'match'}), name='get_match')
]
我在网上搜索并找到了类似的 context
,但只得到 3 个默认字段:request
、view
和 format
,没有提及我的自定义数据。
我的模特:
class Match(models.Model):
sender = models.ForeignKey(
Client,
on_delete=models.CASCADE,
related_name='senders'
)
recipient = models.ForeignKey(
Client,
on_delete=models.CASCADE,
related_name='recipients'
)
class Meta:
app_label = 'clients'
db_table = 'matches'
verbose_name = 'match'
verbose_name_plural = 'matches'
constraints = [
models.UniqueConstraint(
fields=['sender', 'recipient'],
name='unique_match'
)
]
我的序列化程序:
class MatchSerializer(serializers.ModelSerializer):
sender = serializers.HiddenField(default=serializers.CurrentUserDefault())
def validate(self, data):
if data['sender'] == self.context['recipient']:
raise serializers.ValidationError('You cannot match yourself')
return data
def create(self, validated_data):
return Match.objects.create(
sender=validated_data['sender'],
recipient=self.context['recipient']
)
class Meta:
model = Match
fields = ['sender']`
我的模型视图集:
class MatchMVS(ModelViewSet):
queryset = Match.objects.all()
serializer_class = MatchSerializer
http_method_names = ['post']
permission_classes = [IsAuthenticated]
# without and with doesn't work
def get_serializer_context(self):
context = super(MatchMVS, self).get_serializer_context()
context.update({
"recipient": Client.objects.get(pk=23)
# extra data
})
return context
@action(detail=True, methods=['POST'], name='send_your_match')
def match(self, request, pk=None):
sender = request.user
recipient = Client.objects.get(pk=pk)
serializer = MatchSerializer(context={'request': request, 'recipient': recipient},
data=request.data)
data_valid = serializer.is_valid(raise_exception=True)
if data_valid:
recipient = serializer.save()
is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
if is_match:
send_mail(
f'Hello, {sender.first_name}',
f'You got match with {recipient.first_name}! '
f'Your`s partner email: {recipient.email}',
settings.EMAIL_HOST_USER,
[sender.email],
fail_silently=False,
)
send_mail(
f'Hello, {recipient.first_name}',
f'You got match with {sender.first_name}! '
f'Your`s partner email: {sender.email}',
settings.EMAIL_HOST_USER,
[recipient.email],
fail_silently=False,
)
return Response(recipient.email, 201)
else:
return Response(f'Your sympathy has been sent to {recipient.username}.', 201)
我正在通过 PyCharm 和 Postman 进行调试,但仍然无法理解我的错误在哪里。希望你能帮我解决它。
您的代码 right.It 应该可以工作。但是我不知道在哪里 issue.You 可以试试下面修改后的代码。
class MatchSerializer(serializers.ModelSerializer):
def validate(self, data):
if data['sender'] == data['recipient']:
raise serializers.ValidationError('You cannot match yourself')
return data
class Meta:
model = Match
fields = ['sender', 'recipient']
class MatchMVS(ModelViewSet):
queryset = Match.objects.all()
serializer_class = MatchSerializer
http_method_names = ['post']
permission_classes = [IsAuthenticated]
@action(detail=True, methods=['POST'], name='send_your_match')
def match(self, request, pk=None):
sender = request.user
recipient = Client.objects.get(pk=pk)
serializer = MatchSerializer(data={**request.data, 'recipient': recipient.id})
data_valid = serializer.is_valid(raise_exception=True)
if data_valid:
recipient = serializer.save()
is_match = Match.objects.filter(sender=recipient, recipient=sender).exists()
if is_match:
send_mail(
f'Hello, {sender.first_name}',
f'You got match with {recipient.first_name}! '
f'Your`s partner email: {recipient.email}',
settings.EMAIL_HOST_USER,
[sender.email],
fail_silently=False,
)
send_mail(
f'Hello, {recipient.first_name}',
f'You got match with {sender.first_name}! '
f'Your`s partner email: {sender.email}',
settings.EMAIL_HOST_USER,
[recipient.email],
fail_silently=False,
)
return Response(recipient.email, 201)
else:
return Response(f'Your sympathy has been sent to {recipient.username}.', 201)
问题是我自己不注意,错误的viewset被链接到url
urlpatterns = [
path('clients/<int:pk>/match', views.MatchCreateAPIView.as_view(), name='get_match')
]
而不是:
urlpatterns = [
path('clients/<int:pk>/match', views.MatchMVS.as_view({'post': 'match'}), name='get_match')
]