Django many-to-many model DRF

你。 提交于 2019-12-20 06:12:01

问题


I have the following model structure:

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']

My view looks like this:

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)

After calling the view function, a classifier gets created in the database. But after that, I get the following error:

TypeError: 'Account' object is not iterable

The error gets thrown in this line:

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

Anyone how can help me with this?


回答1:


There are two problems here:

  1. Showing nested relationships for M2M field:

If the field is used to represent a to-many relationship, you should add the many=True flag to the serializer field.

So you need to add many=True to AccountSerializer:

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

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.

So if you look at the example and the documentation it seems that you need to implement create or update method.




回答2:


You need to set many=True when dealing with multiple relation - either a m2m or a reversed FK:

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



回答3:


Since your Author field is many to many, you will need to override the create method on your serializer.

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

You will also probably need to set the update method on the serializer, the behavior here can be tricky so make sure you test and make sure the behavior is what you expect.




回答4:


Ok, my previous answer, though could be an issue, isn't the root cause of the actual crash.

When calling the serializer, you set:

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

However, author is a ManyToManyField which means you should call the serializer as:

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

NB: you still require the many=True on the serializer's author field.




回答5:


Please check...

your 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')

your 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']

and finally your view.py is

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)


来源:https://stackoverflow.com/questions/36285140/django-many-to-many-model-drf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!