我有一个自定义的用户模型和订阅模型,其中包含ForeignKey
s to subscribe和user to subscribe.
class Subscription(models.Model):
user = models.ForeignKey(
ApiUser,
on_delete=models.CASCADE,
related_name='subscriber'
)
subscription = models.ForeignKey(
ApiUser,
on_delete=models.CASCADE,
related_name='subscriptions'
)
此外,我有用于订阅的viewset和两个序列化器:写和读.
class SubscribeViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = ApiUser.objects.all()
serializer_class = SubscriptionSerializerForRead
permission_classes = (permissions.AllowAny,)
def get_queryset(self):
queryset = ApiUser.objects.all().annotate(
is_subscribed=Case(
When(
subscribtions__exact=self.request.user.id,
then=Value(True)
),
default=Value(False),
output_field=BooleanField()
)
).order_by('id')
return queryset
def get_serializer_context(self):
context = super().get_serializer_context()
context.update({'subscription_id': self.kwargs['pk']})
return context
def get_serializer_class(self):
if self.request.method not in permissions.SAFE_METHODS:
return SubscriptionSerializerForWrite
return SubscriptionSerializerForRead
@action(
methods=['POST'],
detail=True,
url_path='subscribe'
)
def subscribe(self, request, pk):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
class SubscriptionSerializerForRead(serializers.ModelSerializer):
is_subscribed = serializers.BooleanField()
class Meta:
model = ApiUser
fields = (
'email',
'id',
'username',
'first_name',
'last_name',
'is_subscribed'
)
class SubscriptionSerializerForWrite(serializers.ModelSerializer):
user = serializers.StringRelatedField(
required=False,
read_only=True,
default=serializers.CurrentUserDefault()
)
subscription = serializers.PrimaryKeyRelatedField(
read_only=True
)
class Meta:
model = Subscription
fields = ('user', 'subscription')
def validate(self, attrs):
attrs['user'] = self.context['request'].user
attrs['subscription_id'] = self.context['subscription_id']
if self.context['request'].user.id == self.context['subscription_id']:
raise serializers.ValidationError(
'Cannot subscribe to yourself'
)
return attrs
def to_representation(self, instance):
return SubscriptionSerializerForRead(
instance=instance.subscription
).data
订阅成功后,我需要返回订阅用户数据和附加值is_subscribed
的响应.我试着通过视图集中的annotate
个查询集来实现这一点,但作为回应,我总是得到一个错误:
backend-1 | AttributeError: Got AttributeError when attempting to get a value for field `is_subscribed` on serializer `SubscriptionSerializerForRead`.
backend-1 | The serializer field might be named incorrectly and not match any attribute or key on the `ApiUser` instance.
backend-1 | Original exception text was: 'ApiUser' object has no attribute 'is_subscribed'.
我如何才能使这个工作和是什么导致了这个问题?同样的注释方法适用于我的项目中的其他m2m相关模型,但用户模型由于某种原因而失败