Ответ 1
Спасибо @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)
обратите внимание, что нет сохранения объекта в какой-либо БД в Сериализаторе. Я просто создаю или обновляю объект, а затем возвращаю его.
Теперь представление выглядит так:
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...
Я также сказал в своем оригинальном посте:
Все это кажется более влюбленным в объекты БД, которые в данном конкретном случае именно то, чего я пытаюсь избежать.
Это утверждение также было неверным, поскольку тот факт, что методы создания и обновления не должны ничего сохранять в какой-либо БД.
Одно из предостережений заключается в том, что код является функциональным, но, очевидно, я просто обволакиваю некоторые из изменений DRF2.x- > 3.x, поэтому я мог бы делать это не-DRF-способом. Если да, то кто-то, кто знает, не стесняйтесь сказать мне, как это сделать лучше.:)