Django 多对多模型 DRF
Django many-to-many model DRF
我有以下模型结构:
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
我的观点是这样的:
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)
调用视图函数后,在数据库中创建了一个分类器。但在那之后,我收到以下错误:
TypeError: 'Account' object is not iterable
这一行抛出错误:
instance = serializer.save(author=self.request.user)
谁能帮我解决这个问题?
处理多重关系时需要设置many=True
- m2m 或反向 FK:
author = AccountSerializer(read_only=True, required=False, many=True)
由于您的 Author 字段是多对多的,因此您需要重写序列化程序上的创建方法。
def create(self, validated_data):
author = validated_data.pop(author, None)
project = Project.objects.save(validated_data)
if author:
project.author.add(author)
您可能还需要在序列化程序上设置更新方法,此处的行为可能很棘手,因此请务必进行测试并确保行为符合您的预期。
好的,我之前的回答虽然可能是一个问题,但并不是实际崩溃的根本原因。
调用序列化程序时,您设置:
instance = serializer.save(author=self.request.user)
但是,作者是 ManyToManyField
,这意味着您应该将序列化器调用为:
instance = serializer.save(author=[self.request.user])
注意:您仍然需要序列化程序作者字段中的 many=True。
请检查...
你的model.py
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
你的serializer.py
class ProjectSerializer(serializers.ModelSerializer):
author = AccountSerializer(read_only=True, required=False)
class Meta:
model = Project
fields = ('id', 'author', 'name')
read_only_fields = ('id')
def get_validation_exclusions(self, *args, **kwargs):
exclusions = super(ProjectSerializer, self).get_validation_exclusions()
return exclusions + ['author']
最后你的view.py是
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)
这里有两个问题:
- 显示 nested relationships M2M 字段:
If the field is used to represent a to-many relationship, you should add the many=True
flag to the serializer field.
所以你需要将many=True
添加到AccountSerializer
:
author = AccountSerializer(read_only=True, required=False, many=True)
By default nested serializers are read-only
. If you want to support write-operations to a nested serializer field you'll need to create create()
and/or update()
methods in order to explicitly specify how the child relationships should be saved.
因此,如果您查看示例和文档,您似乎需要实施 create
或 update
方法。
我有以下模型结构:
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
我的观点是这样的:
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)
调用视图函数后,在数据库中创建了一个分类器。但在那之后,我收到以下错误:
TypeError: 'Account' object is not iterable
这一行抛出错误:
instance = serializer.save(author=self.request.user)
谁能帮我解决这个问题?
处理多重关系时需要设置many=True
- m2m 或反向 FK:
author = AccountSerializer(read_only=True, required=False, many=True)
由于您的 Author 字段是多对多的,因此您需要重写序列化程序上的创建方法。
def create(self, validated_data):
author = validated_data.pop(author, None)
project = Project.objects.save(validated_data)
if author:
project.author.add(author)
您可能还需要在序列化程序上设置更新方法,此处的行为可能很棘手,因此请务必进行测试并确保行为符合您的预期。
好的,我之前的回答虽然可能是一个问题,但并不是实际崩溃的根本原因。
调用序列化程序时,您设置:
instance = serializer.save(author=self.request.user)
但是,作者是 ManyToManyField
,这意味着您应该将序列化器调用为:
instance = serializer.save(author=[self.request.user])
注意:您仍然需要序列化程序作者字段中的 many=True。
请检查...
你的model.py
class Account(AbstractBaseUser):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
first_name = models.CharField(max_length=40, blank=True)
last_name = models.CharField(max_length=40, blank=True)
tagline = models.CharField(max_length=140, blank=True)
is_admin = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
class Project(models.Model):
author = models.ManyToManyField(Account)
name = models.CharField(max_length=40, default='NewBook')
你的serializer.py
class ProjectSerializer(serializers.ModelSerializer):
author = AccountSerializer(read_only=True, required=False)
class Meta:
model = Project
fields = ('id', 'author', 'name')
read_only_fields = ('id')
def get_validation_exclusions(self, *args, **kwargs):
exclusions = super(ProjectSerializer, self).get_validation_exclusions()
return exclusions + ['author']
最后你的view.py是
class ProjectViewSet(viewsets.ModelViewSet):
queryset = Project.objects.order_by('-name')
serializer_class = ProjectSerializer
def perform_create(self, serializer):
instance = serializer.save(author=self.request.user)
return super(ProjectViewSet, self).perform_create(serializer)
这里有两个问题:
- 显示 nested relationships M2M 字段:
If the field is used to represent a to-many relationship, you should add the
many=True
flag to the serializer field.
所以你需要将many=True
添加到AccountSerializer
:
author = AccountSerializer(read_only=True, required=False, many=True)
By default nested serializers are
read-only
. If you want to support write-operations to a nested serializer field you'll need to createcreate()
and/orupdate()
methods in order to explicitly specify how the child relationships should be saved.
因此,如果您查看示例和文档,您似乎需要实施 create
或 update
方法。