django - 在 django 中根据某些条件创建对象
问题描述
我有一个模型Showcase
,用户可以用来展示项目。我正在尝试实现一个案例,Administrators
展示中的任何管理员都可以通过Collaborator
模型添加协作者。当我在下面运行我的代码时,我得到
IntegrityError at /api/showcase/the-gods-must-be-crazy-zz2fox/collaborator/create/
NOT NULL constraint failed: showcase_collaborator.user_id
.
模型.py
class Showcase(models.Model):
title = models.CharField(max_length=50)
description = models.TextField(null=True)
skill_type = models.ForeignKey(Skill, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="Showcases")
content = models.TextField(null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
voters = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="upvotes")
slug = models.SlugField(max_length=255, unique=True)
administrator = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="administrators", blank=True)
class Collaborator(models.Model):
post = models.ForeignKey(Showcase, on_delete=models.CASCADE, related_name="collaborated_showcases")
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, related_name="collaborators")
skill = models.ForeignKey(Skill, on_delete=models.CASCADE, null=True, related_name="creative_type")
role = models.TextField(null=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
串行器
class CollaboratorSerializer(serializers.ModelSerializer):
post = serializers.SlugRelatedField(read_only=True, slug_field='slug')
class Meta:
model = Collaborator
exclude = ['created_on', 'updated_on']
class ShowcaseAdminSerializer(serializers.ModelSerializer):
administrator = serializers.SlugRelatedField(slug_field='slug', many=True, queryset=User.objects.all())
class Meta:
model = Showcase
fields = ['administrator',]
def update(self, instance, validated_data):
users = validated_data.get('administrator')
for user in users:
instance.administrator.add(user)
return instance
视图.py
class collaboratorCreateView(APIView):
'''
add collaborator to a showcase
'''
serializer_class = CollaboratorSerializer
permission_classes = [IsAdmin]
def post(self, request, slug):
showcase = get_object_or_404(Showcase, slug=slug)
try:
self.check_object_permissions(request, showcase)
collaborator = Collaborator.objects.create(
post = showcase
)
serializer = self.serializer_class(collaborator, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except APIException:
return Response(status=status.HTTP_403_FORBIDDEN)
网址
path("<slug:slug>/collaborator/create/", qv.collaboratorCreateView.as_view(), name="add-collaborator-to-showcase"),
另外,作为额外的,我想知道如果可能的话,如何防止创建重复用户作为协作者。我猜测 if 语句可能会解决问题,但我对此感到迷茫,因为我不知道如何获取用户输入以检查视图。
解决方案
正如错误所说,您需要user
在此处为模型中的属性提供值。所以你可以这样做。
首先,更新序列化器:
class CollaboratorSerializer(serializers.ModelSerializer):
post = serializers.SlugRelatedField(read_only=True, slug_field='slug')
class Meta:
model = Collaborator
exclude = ['created_on', 'updated_on', 'user']
def validate_user(self, value):
showcase = self.context.get('post')
if showcase.collaborated_showcases.filter(user=value).exists():
raise serializers.ValidationError("Can't add an existing collaborator to a showcase")
return value
def create(self, validated_data):
validated_data['post'] = self.context['post']
return super(CollaboratorSerializer, self).create(validated_data)
然后更新视图:
class collaboratorCreateView(APIView):
'''
add collaborator to a showcase
'''
serializer_class = CollaboratorSerializer
permission_classes = [IsAdmin]
def post(self, request, slug):
showcase = get_object_or_404(Showcase, slug=slug)
try:
self.check_object_permissions(request, showcase)
serializer = self.serializer_class(data=request.data, context={'post':showcase})
if serializer.is_valid():
serializer.save()
在这里,我showcase
通过 . 将对象传递给 Collaborator context
。