Sup*_*ngo 12 python django serialization django-rest-framework
我正在从2.4升级到DRF3.1.1.我使用自定义序列化程序来创建不是模型的对象的实例.
在2.4中,这很容易做到这一点,因为在序列化器中,我会创建对象restore_object().在视图中,我调用serializer.is_valid()然后将该对象的实例从序列化器中弹出serializer.object.然后我可以做任何我想做的事.
随着3.x的更改,将实例从对象中取出更难,因为创建和更新方法应该进行保存,并且"serializer.object"不再可用.
作为一个例子,我曾经把它作为我的"UserRegistration"对象.这不是模型,因为它是一个便利对象,服务器解析并将数据存储在许多其他对象/ db表中.
class UserRegistration(object):
def __init__(self, full_name, stage_name, password="", email="", locale="en_US"):
self.full_name = full_name
self.password = password
self.locale = locale
self.email = email
self.stage_name = stage_name
Run Code Online (Sandbox Code Playgroud)
这是相关的DRF-2.4串行器:
class UserRegistrationSerializer(serializers.Serializer):
full_name = serializers.CharField(max_length=128, required=False)
stage_name = serializers.CharField(max_length=128)
password = serializers.CharField(max_length=128, required=False)
locale = serializers.CharField(max_length=10, required=False)
# use CharField instead of EmailField for email. We do our own validation later to make for a better error msg.
email = serializers.CharField(max_length=254, required=False)
def restore_object(self, attrs, instance=None):
if instance is not None:
instance.full_name = attrs.get('full_name', instance.full_name)
instance.password = attrs.get('password', instance.password)
instance.locale = attrs.get('locale', instance.locale)
instance.email = attrs.get('email', instance.email)
instance.stage_name = attrs.get('stage_name', instance.stage_name)
return instance
return UserRegistration(**attrs)
Run Code Online (Sandbox Code Playgroud)
然后在我看来,我这样做:
class UserRegistration(APIView):
throttle_classes = ()
serializer_class = UserRegistrationSerializer
def post(self, request, format=None):
event_type = "user_registration"
serializer = UserRegistrationSerializer(data=request.DATA, context={'request': request})
try:
if serializer.is_valid():
user_registration = serializer.object
# save user_registration pieces in various places...
Run Code Online (Sandbox Code Playgroud)
然而,在DRF3中,我serializer.object走了.文档说使用"验证" serializer.validated_data,但这只是一个哈希而不是真正的对象.有没有办法获得对象?
整个事情看起来更像是DB对象,在这种特殊情况下,这正是我想要避免的.
我刚刚错过了一些新的DRF3概念吗?
Sup*_*ngo 12
感谢@levi回答的开头,但不幸的是,这不是全部,所以我认为这是一个更完整的答案.
我原来问:
我刚刚错过了一些新的DRF3概念吗?
原来......是的.我曾是.文档谈论新的Single-step object creation,这使我认为序列化和模型已经变得更加紧密耦合.这个想法是不正确的,因为如果你编写自己的自定义序列化程序,那么你可以在新的和方法中做实际的对象保存(或不保存). serializer.update()serializer.create()
我还问:
在2.4中,这很容易做到这一点,因为在序列化器中,我将在restore_object()中创建对象.在视图中,我调用serializer.is_valid()然后使用serializer.object将该对象的实例弹出序列化程序.然后我可以做任何我想做的事.
随着3.x的更改,将实例从对象中取出更难,因为创建和更新方法应该进行保存,并且"serializer.object"不再可用.
虽然没有serializer.object你可以用来从调用后拉出创建的对象serializer.is_valid(),但该serializer.save()方法返回对象本身,在我的情况下就好了.
事实证明,代码变化根本不是很大.这是我对DRF-3非常满意的新代码:
class UserRegistration(object):
def __init__(self, full_name, stage_name, password="", email="", locale="en_US", notification_pref="ask"):
self.full_name = full_name
self.password = password
self.locale = locale
self.email = email
self.stage_name = stage_name
class UserRegistrationSerializer(serializers.Serializer):
full_name = serializers.CharField(max_length=128, required=False)
stage_name = serializers.CharField(max_length=128)
password = serializers.CharField(max_length=128, required=False)
locale = serializers.CharField(max_length=10, required=False)
# use CharField instead of EmailField for email. We do our own validation later to make for a better error msg.
email = serializers.CharField(max_length=254, required=False)
def update(self, instance, validated_data):
instance.full_name = validated_data.get('full_name', instance.full_name)
instance.password = validated_data.get('password', instance.password)
instance.locale = validated_data.get('locale', instance.locale)
instance.email = validated_data.get('email', instance.email)
instance.stage_name = validated_data.get('stage_name', instance.stage_name)
return instance
def create(self, validated_data):
return UserRegistration(**validated_data)
Run Code Online (Sandbox Code Playgroud)
请注意,没有将对象保存到Serializer中的任何DB.我只是创建或更新对象然后返回它.
现在视图看起来像这样:
class UserRegistration(APIView):
throttle_classes = ()
serializer_class = UserRegistrationSerializer
def post(self, request, format=None):
event_type = "user_registration"
serializer = UserRegistrationSerializer(data=request.DATA, context={'request': request})
try:
if serializer.is_valid():
user_registration = serializer.save()
# save user_registration pieces in various places...
Run Code Online (Sandbox Code Playgroud)
我在原帖中也说过:
整个事情看起来更像是DB对象,在这种特殊情况下,这正是我想要避免的.
此声明也是不正确的,因为创建和更新方法不必将任何内容保存到任何数据库.
这里需要注意的是代码是有用的,但显然我只是围绕一些DRF2.x-> 3.x更改,所以我可以用非DRF方式来做这件事.如果是这样,有人知道请随时告诉我如何做得更好.:)
是的,您可以使用 DRF 3 获取对象本身。您的update方法应该具有此签名update(self, instance, validated_data)
你的序列化器应该是这样的:
class UserRegistrationSerializer(serializers.Serializer):
full_name = serializers.CharField(max_length=128, required=False)
stage_name = serializers.CharField(max_length=128)
password = serializers.CharField(max_length=128, required=False)
locale = serializers.CharField(max_length=10, required=False)
# use CharField instead of EmailField for email. We do our own validation later to make for a better error msg.
email = serializers.CharField(max_length=254, required=False)
def update(self, instance, validated_data):
// here instance is the object .
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5913 次 |
| 最近记录: |