DRF使用直通模型创建和检索m2m

时间:2016-07-05 03:43:16

标签: python django django-rest-framework

我想通过模型

保存m2m关系

models.py

from django.db import models

class Student(utils.PersonalDetailsMixin, utils.ContactDetailsMixin, TimeStampedModel):
    guardians = models.ManyToManyField('core.Guardian', through='Relation')

class Relation(models.Model):
    student = models.ForeignKey('core.Student')
    guardian = models.ForeignKey('core.Guardian')
    relation_type = models.CharField(max_length=1, choices=utils.RELATION_CHOICES)
    # Only used when relation_type is Other
    relation_name = models.CharField(max_length=25, null=True, blank=True)

    class Meta:
        unique_together = (
            ('student', 'guardian')
        )

class Guardian(utils.PersonalDetailsMixin, utils.ContactDetailsMixin, TimeStampedModel):
    pass

serializers.py

class StudentSerializer(serializers.ModelSerializer):
    guardians = GuardianSerializer(many=True)

    class Meta:
        model = Student


class GuardianSerializer(serializers.ModelSerializer):
    class Meta:
        model = Guardian

class RelationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Relation

首先:

relation_type = serializers.ChoiceField(choices=RELATION_CHOICES)
relation_name = serializers.CharField(max_length=25, required=False, allow_null=True, allow_blank=True)

我尝试将relation_typerelation_name添加到GuardianSerializer,但收到此错误

Got AttributeError when attempting to get a value for field `relation_type` on serializer `GuardianSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Guardian` instance.
Original exception text was: 'Guardian' object has no attribute 'relation_type'.

哪个好DRF应该给出这个错误。

第二

class StudentSerializer(serializers.ModelSerializer):
    school = serializers.HiddenField(default='')
    guardians = RelationSerializer(source='relation_set', many=True)

class GuardianSerializer(serializers.ModelSerializer):
    class Meta:
        model = Guardian

class RelationSerializer(serializers.ModelSerializer):
    guardian = GuardianSerializer(many=True)

    class Meta:
        model = Relation

RelationSerializer添加到StudentSerializer,将GuardianSerializer添加到RelationSerializer

现在我得到了'Guardian' object is not iterable

Traceback:

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
  87.             return self.dispatch(request, *args, **kwargs)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  466.             response = self.handle_exception(exc)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list
  48.         return Response(serializer.data)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  674.         ret = super(ListSerializer, self).data

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in data
  239.                 self._data = self.to_representation(self.instance)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  614.             self.child.to_representation(item) for item in iterable

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  472.                 ret[field.field_name] = field.to_representation(attribute)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  614.             self.child.to_representation(item) for item in iterable

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  472.                 ret[field.field_name] = field.to_representation(attribute)

File "/home/prime/.virtualenvs/omapi/local/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation
  614.             self.child.to_representation(item) for item in iterable

Exception Type: TypeError at /v1/students/
Exception Value: 'Guardian' object is not iterable

如何使用Student instanceGuardian保存Relation。如何实现此功能我知道需要自定义创建方法,但如何通过此错误传递。或者是否有其他方式来serialize and deserialize这种关系。

2 个答案:

答案 0 :(得分:1)

您需要将MembershipSerializer嵌套在GroupSerializer中,替换PersonSerializer并使MembershipSerializer具有嵌套PersonSerializer,以便这个工作。

或者,您可以将PersonSerializer替换为常规Serializer并自行明确获取数据集,而不是依赖于自动DRF。

编辑问题版本:

class RelationSerializer(serializers.ModelSerializer):
    guardian = GuardianSerializer(many=True)

由于RelationGuardian之间的关系是ForeignKey,因此您需要在此删除many=True

答案 1 :(得分:1)

class MembershipSerializer(serializers.ModelSerializer):
    person = serializers.PrimaryKeyRelatedField(queryset=Person.objects.all())
    group = serializers.PrimaryKeyRelatedField(queryset=Group.objects.all())

    class Meta:
        model = Membership
        fields = ('person', 'group', 'date_joined', 'invite_reason')


class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        fields = ('name')

class GroupSerializer(serializers.ModelSerializer):

    class Meta:
        model = Group
        fields = ('name')

希望答案有所帮助:)