我需要在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'
)
]
答案 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)
...
最后,一种更可重用的方法是为提供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
(基本上是CreateModelMixin
和UpdateModelMixin
)在执行其操作(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())