django - 如何使用 django rest 框架正确保存和验证对象
问题描述
我正在学习django rest framework
,我发现正确验证和保存对象的问题。
当我收到创建对话的请求时,我首先需要创建一个对话,然后向其中添加参与者。
这是Dialog
模型的代码:
class DialogManager(models.Manager):
def create_dialog(self, name):
max_length(name, 30)
dialog = self.model(name=name)
dialog.save()
return dialog
class Dialog(models.Model):
name = models.CharField(null=False)
created_at = models.DateTimeField(auto_now_add=True)
objects = DialogManager()
我的Participant
模型:
class ParticipantManager(models.Manager):
def create_participant(self, dialog, user, role="user"):
if role not in ["user", "admin"]:
raise ValueError('Incorrect role for the user')
max_length(role, 30)
participant = Participant(role=role, dialog=dialog, user=user)
participant.save()
return participant
class Participant(models.Model):
role = models.CharField(null=False)
dialog = models.ForeignKey(Dialog, on_delete=models.CASCADE)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
objects = ParticipantManager()
class Meta:
unique_together = ('dialog', 'user',)
并Dialog
设置:
class DialogSet(viewsets.ModelViewSet):
queryset = Dialog.objects.all()
serializer_class = DialogSerializer
pagination_class = DialogSetPagination
def create(self, request):
data = request.data
users = CustomUser.objects.filter(pk__in=data['ids'])
dialog_serializer = DialogSerializer(data=data)
if not dialog_serializer.is_valid():
return Response(dialog_serializer.errors, status.HTTP_400_BAD_REQUEST)
with transaction.atomic():
dialog = dialog_serializer.save()
i = 0
for user in users:
participant_serializer = ParticipantSerializer(data={'dialog': dialog.pk, 'user': user.pk, 'role': 'user'})
if not participant_serializer.is_valid():
return Response(participant_serializer.errors, status.HTTP_400_BAD_REQUEST)
i += 1
return Response(dialog, status.HTTP_201_CREATED)
问题是我可以保存一个对象Dialog
,然后验证participants
对象,它们将是无效的。我需要回滚。我可以在不使用事务的情况下更改创建dialog
和对象的过程吗?participants
这让我想到了许多其他问题。
有人告诉我,模型和序列化程序中的双重验证不是一个好主意。据我了解,最好将所有验证存储在模型中,但在序列化程序中仅添加与数据库无关的验证?
因此,我将自定义
create
方法添加到模型Dialog
和Participant
. 但在这种情况下,事实证明创建方法也处理验证,我知道django
模型中没有在创建对象之前调用的验证方法。那么,在哪里确定验证?还有另一个问题,
create
据我了解,方法涉及保存对象。我需要将保存的dialog
对象放入对象中,但如果对象无效participants
,我将需要回滚更改。participants
创建方法要保存对象吗?当我没有将序列化程序的
role
密钥Participant
放在我的DialogSet
然后调用中.is_valid()
时,它会调用validate
序列化程序,它会检查是否指定了角色。因此,我再次在validate
方法和create_participant
. 但是我想role
通过在我的序列化程序中调用模型验证方法来检查是否指定,然后调用create_participant
以保存对象。我可以做吗?
总而言之,我想得到这样的东西:
class ParticipantSerializer(serializers.ModelSerializer):
class Meta:
model = Participant
fields = '__all__'
def validate(self, data):
data = ParticipantManager.validate(**data)
return data
def create(self, validated_data):
role = validated_data['role']
user = validated_data['user']
dialog = validated_data['role']
participant = Participant.objects.create_participant(dialog, user, role)
return participant
class ParticipantManager(models.Manager):
def create_participant(self, dialog, user, role):
participant = Participant(dialog=dialog, user=user, role=role)
participant.save()
return participant
def validate(self, data):
## validate data
return data
如果此代码不正确,请告诉我如何正确执行。
解决方案
抱歉,我已经阅读了 Django 中的 clean() ,它解决了我的问题。问题已结束。
推荐阅读
- react-navigation - 在 react-navigation 的嵌套堆栈导航中。它不会向上滚动
- php - PHP echo 在源代码中实现在哪里?
- javascript - Javascript 确认重定向无法正常工作
- gremlin - 优化 gremlin 查询以避免图的多次遍历
- javascript - TypeScript:省略只读对象文字
- javascript - 删除构建 Angular 8 后脚本中的内容
- kubernetes-helm - CustomResourceDefinition 和 ClickHouseInstallation 的 Helm 模板顺序
- google-bigquery - 如何查看非数字列中的所有值(ISNUMERIC() 等效?)
- amazon-web-services - CloudFormation Fn::Transform 操作:降低 -> 语法错误
- php - 无法将变量传递给 Laravel x 组件