简体   繁体   English

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

[英]Get logged user information in serializers Django Rest + Django JWT

I need to get a FK info in logged User on ModelSerializer to add a new models. 我需要在ModelSerializer的登录用户中获取FK信息,以添加新模型。

In this case User->Business and Client->Business. 在这种情况下,用户->业务和客户->业务。 When post client I need to set Business id using the logged user Business. 发布客户后,我需要使用登录的用户Business来设置Business ID。

It's important to say all other models have the same behavior. 重要的是要说所有其他模型具有相同的行为。 I'm looking for some generic solution for this problem. 我正在寻找一些通用的解决方案来解决这个问题。

Client Model 客户模型

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'))

User Model 用户模型

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 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'
        )
    ]

Access request inside a serializer 序列化器内的访问请求

Within the serializer you have access to the serializer context that can include the request instance 在序列化程序中,您可以访问可以包含请求实例的序列化程序上下文

class ClientSerializer(serializers.ModelSerializer):
    ...

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

Request is only acessible if you pass it when instantiate the serializer 仅当实例化序列化程序时传递请求时,请求才是必需的

Pass extra arguments to a serializer via save() 通过save()额外的参数传递给序列化器

It is also possible to pass extra arguments to a serializer during the save() method call save()方法调用期间,还可以将额外的参数传递给序列化程序

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

Create a mixin to set business 创建一个mixin以开展业务

Finally, a more reusable way is create a mixin for views that provides create and/or update actions, then overwrite perform_create() and perform_update() methods 最后,一种更可重用的方法是为提供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 (basically CreateModelMixin and UpdateModelMixin ) use these methods to call the save() method from serializer when executing its actions ( create() , update() and partial_update() , ie POST , PUT and PATCH ) ModelViewSet (基本上是CreateModelMixinUpdateModelMixin )在执行其动作( create()update()partial_update() ,即POSTPUTPATCH )时,使用这些方法从序列化程序中调用save()方法。

Inspired by serializers.CurrentUserDefault() magic I wrote CurrenUserBusinessDefault but set_context with current user business. 受到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__)

So it's accessible like the default method 因此可以像默认方法一样访问

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM