我有一个AngularJS项目,它通过Django Rest Framework(DRF)将Django用作框架。Django Rest框架与自己相关的多对多的领域
我已经创建了一个组模型并为它设置了一个序列化器类,但是我想现在在该模型上建立一个名为related_groups
的新字段,它将引用与主键数组相同的模型。
虽然我不知道是否可以在序列化程序中自我引用,但我不知道如何从前端通过相关组,从而可以由用户挑选和选择谁拥有该组织。我希望该字段引用其他Group行的主键,并遍历该组的集合以建立相关的组关系。
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = mod.Group
fields = (
'group_id',
'group_name',
'category',
'related_groups',
)
,并表示似乎正是我想要的:
GroupSerializer():
group_id = IntegerField(read_only=True)
group_name = CharField(max_length=100)
category = CharField(max_length=256, required=False
related_groups = PrimaryKeyRelatedField(many=True, queryset=Group.objects.all(), required=False)
和模型表示为这样:
class Group(models.Model):
"""
Model definition of a Group. Groups are a collection of users (i.e.
Contacts) that share access to a collection of objects (e.g. Shipments).
"""
group_id = models.AutoField(primary_key=True)
group_name = models.CharField(max_length=100)
owner_id = models.ForeignKey('Owner', related_name='groups')
category = models.CharField(max_length=256)
related_groups = models.ManyToManyField('self', blank=True, null=True)
history = HistoricalRecords()
def __unicode__(self):
return u'%s' % (self.group_name)
def __str__(self):
return '%s' % (self.group_name)
访问该模型的观点是非常简单的CRUD视图:
@api_view(['GET', 'PUT', 'DELETE'])
@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated, HasGroupAccess))
def group_detail(request, pk, format=None):
group, error = utils.get_by_pk(pk, mod.Group, request.user)
if error is not None:
return error
if request.method == 'GET':
serializer = ser.GroupSerializer(group)
return Response(serializer.data)
elif request.method == 'PUT':
return utils.update_object_by_pk(request, pk, mod.Group,
ser.GroupSerializer)
elif request.method == 'DELETE':
return utils.delete_object_by_pk(request.user, pk, mod.Group)
其中要求一些消毒和验证方法:
def update_object_by_pk(request, pk, obj_type, serializer):
try:
with transaction.atomic():
obj, error = select_for_update_by_pk(pk, obj_type, request.user)
if error is not None:
return error
obj_serializer = serializer(obj, data=request.data)
if obj_serializer.is_valid():
obj_serializer.save()
else:
response = ("Attempt to serialize {} with id {} failed "
"with errors {}").format(str(obj_type), str(pk),
str(serializer.errors))
return Response(response, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
response = ("Error attempting to update {} with ID={}. user={}, "
"error={}".format(str(obj_type), str(pk),
str(request.user.email), str(e)))
return Response(response, status=status.HTTP_400_BAD_REQUEST)
else:
resp_str = ("Successfully updated {} with ID={}".format(str(obj_type),
str(pk)))
return Response(resp_str, status=status.HTTP_200_OK)
的呼叫:
def select_for_update_by_pk(pk, mod_type, user):
response = None
obj = None
try:
obj = mod_type.objects.select_for_update().get(pk=pk)
except mod_type.DoesNotExist:
resp_str = ("{} could not be found with ID={}.".
format(str(mod_type), str(pk)))
response = Response(resp_str, status=status.HTTP_404_NOT_FOUND)
return obj, response
这只是一个包装围绕select_for_update()
Django的方法。
迁移创建了一个名为group_related_groups的新表,其中包含ID,from_group和to_group列,由Django用作联结/查找来建立这些关系。
我可以单独写入该端点,但序列化程序GroupSerializer似乎不希望允许通过默认多个值。
因此,使用PUT请求将PUT值设为'2'以PK为1组是成功的。然而,试图将['2','3']
,[2,3]
,2,3
和'2','3'
跟踪回通过以实用的方法,我看到它serializer.is_valid()
失败的请求,这样让我觉得这是一个many=True
问题,但我不t知道哪个关系序列化器用于这个特定的自引用ManyToManyField问题。
调试时,我输出serializer.is_valid()错误,系统日志是这样的:
response = ("Attempt to serialize {} with id {} failed "
"with errors {}").format(str(obj_type), str(pk),
str(serializer.errors))
logger.exception(response)
而且我得到这个异常消息作为响应:
Message: "Attempt to serialize <class 'bioapi.models.Group'> with id 1 failed with errors
"
obj_serializer的调试错误输出。错误是
obj_serializer.error of {'related_groups': ['Incorrect type. Expected pk value, received str.']}
而这里的调试讯息支付上request.data:
{'group_name': 'Default Guest Group', 'related_groups': [1], 'group_id': 2, 'category': 'guest'}
其成功,
<QueryDict: {'group_name': ['requestomatic'], 'related_groups':['2,2'], category': ['guest']}>
失败。现在看这个,我想知道Postman表单数据格式是否是问题。如果是这种情况,我会觉得很愚蠢。
我可以使用DRF表示从模型到模型本身的多对多关系,还是仅需要为关系表使用自定义序列化程序? DRF文档不使用自参考模型,我在网上找到的所有示例都使用多个模型或多个串行器。
是否可以在我的模型中使用ManyToManyField,它是使用Django Rest Framework(DRF)及其序列化器的自引用?如果是这样,怎么样?
请解释一下你的'GroupSerializer的意思() :'在你的第二个片段中 – e4c5
'serializer.is_valid()'失败后,'serializer.errors'的内容是什么?它通常给出很好的提示,为什么它失败。 –
@ e4c5,使用序列化程序关系文档中描述的方法检查序列化程序的关系,这里:http://www.django-rest-framework.org/api-guide/relations/#inspecting-relationships,并且关系似乎是保持秩序。 – Smittles