在序列化程序中获取记录的用户信息Django Rest + Django JWT

时间:2019-01-03 20:33:04

标签: python django-rest-framework django-rest-framework-jwt

我需要在ModelSerializer上已登录的用户中获取FK信息,以添加新模型。

在这种情况下,用户->业务和客户->业务。 发布客户后,我需要使用登录的用户“业务”设置业务ID。

重要的是要说所有其他模型具有相同的行为。我正在寻找一些通用的解决方案来解决这个问题。

客户端模型

class Client(SoftDeletionModel):
    object = ClientManager
    business = models.ForeignKey(Business, related_name='business_clients', on_delete=models.CASCADE)
    company_name = models.CharField(max_length=511, verbose_name=_('Company Name'))
    cnpj = models.CharField(max_length=14, verbose_name=_('CNPJ'))

用户模型

class User(AbstractUser):
"""User model."""

    username = None
    email = models.EmailField(_('email address'), unique=True)
    business = models.ForeignKey(Business, related_name='business', on_delete=models.CASCADE, null=True)

ClientSerializer

class ClientSerializer(serializers.ModelSerializer):
    business = serializers.IntegerField() # here how can I get user.business?
    deleted_at = serializers.HiddenField(default=None)
    active = serializers.BooleanField(read_only=True)
    password = serializers.CharField(write_only=True, required=False, allow_blank=True)
    password_contract = Base64PDFFileField()

class Meta:
    model = Client
    fields = '__all__'
    validators = [
        UniqueTogetherValidator2(
            queryset=Client.objects.all(),
            fields=('cnpj', 'business'),
            message=_("CNPJ already exists"),
            key_field_name='cnpj'
        ),
        UniqueTogetherValidator2(
            queryset=Client.objects.all(),
            fields=('email', 'business'),
            message=_("Email already exists"),
            key_field_name='email'
        )
    ]

2 个答案:

答案 0 :(得分:1)

序列化程序内部的访问请求

在序列化程序内,您可以访问可以包含请求实例的序列化程序上下文

class ClientSerializer(serializers.ModelSerializer):
    ...

    def create(self, validated_data):
        return Client.objects.create(
            business=self.context['request'].user.business,
            **validated_data
        )

仅当实例化序列化程序时将其传递时,请求才是必需的

通过save()

将其他参数传递给序列化器

还可以在save()方法调用期间将额外的参数传递给序列化器

def create(self, request, **kwargs)
    serializer = ClientSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save(business=request.user.business)
    ...

创建一个mixin以开展业务

最后,一种更可重用的方法是为提供create和/或update动作的视图创建一个混合,然后覆盖perform_create()perform_update()方法

class BusinessMixin:
    def perform_create(self, serializer):
        serializer.save(business=self.request.user.business)

    def perform_update(self, serializer):
        serializer.save(business=self.request.user.business)


class ClientViewSet(BusinessMixin, ModelViewSet):
    serializer_class = ClientSerializer
    queryset = Client.objects.all()
    ...

ModelViewSet(基本上是CreateModelMixinUpdateModelMixin)在执行其操作(save(),{{1 }}和create(),即update()partial_update()POST

答案 1 :(得分:0)

受serializers.CurrentUserDefault()的启发,我写了CurrenUserBusinessDefault,但是用当前用户业务写了set_context。

class CurrentUserBusinessDefault(object):
    def set_context(self, serializer_field):
        self.business =  serializer_field.context['request'].user.business

    def __call__(self):
        return self.business

    def __repr__(self):
        return unicode_to_repr('%s()' % self.__class__.__name__)

因此可以像默认方法一样访问

class ClientSerializer(serializers.ModelSerializer):
    business = BusinessSerializer(default=CurrentUserBusinessDefault())