Django多对多模型DRF

时间:2016-03-29 13:04:49

标签: python django django-models django-rest-framework django-orm

我有以下模型结构:

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)

调用view函数后,将在数据库中创建分类器。但在那之后,我收到以下错误:

  

TypeError:'Account'对象不可迭代

此行中出现错误:

instance = serializer.save(author=self.request.user)

任何人如何帮助我?

5 个答案:

答案 0 :(得分:0)

在处理多种关系时需要设置many=True - m2m或反向FK:

author = AccountSerializer(read_only=True, required=False, many=True)

答案 1 :(得分:0)

由于您的“作者”字段是多对多,因此您需要覆盖序列化程序上的create方法。

def create(self, validated_data):
     author = validated_data.pop(author, None)
     project = Project.objects.save(validated_data)
     if author:
         project.author.add(author)

您可能还需要在序列化程序上设置更新方法,此处的行为可能会非常棘手,因此请确保您测试并确保行为符合您的预期。

答案 2 :(得分:0)

好的,我之前的回答虽然可能是一个问题,但并不是实际崩溃的根本原因。

调用序列化程序时,设置:

instance = serializer.save(author=self.request.user)

但是,作者是ManyToManyField,这意味着您应该将序列化程序称为:

instance = serializer.save(author=[self.request.user])

注意:您仍然需要序列化程序的作者字段中的many = True。

答案 3 :(得分:0)

请检查......

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)

答案 4 :(得分:0)

这里有两个问题:

  1. 为M2M字段显示nested relationships
  2.   

    如果该字段用于表示多对多关系,则应将many=True标志添加到序列化程序字段。

    因此,您需要将many=True添加到AccountSerializer

    author = AccountSerializer(read_only=True, required=False, many=True)
    
    1. A writable nested serializer
    2.   

      默认情况下,嵌套序列化程序为read-only。如果要支持对嵌套序列化程序字段的写操作,则需要创建create()和/或update()方法,以便明确指定应如何保存子关系。

      因此,如果您查看示例和文档,您似乎需要实现createupdate方法。