gpt4 book ai didi

angularjs - Django Rest Framework 与其自身相关的多对多字段

转载 作者:行者123 更新时间:2023-12-02 23:37:03 27 4
gpt4 key购买 nike

我有一个 AngularJS 项目,它通过 Django Rest Framework (DRF) 使用 Django 作为框架。

我已经创建了一个 Group 模型并为其设置了一个序列化器类,但是我现在想在该模型上建立一个名为 related_groups 的新字段。 ,它将引用相同的模型(组)作为主键数组。

不过,我不知道是否可以在序列化器中进行自引用,并且我不知道如何从前端传递相关组,这些组可以由用户选择拥有该团体。我希望该字段引用其他组行的主键,并迭代该组集合以建立相关的组关系。

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)

访问该模型的 View 是非常简单的 CRUD View :

@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_lated_groups 的新表,其中包含 ID、from_group 和 to_group 列,Django 将其用作联结/查找来建立这些关系。

我可以单独写入该端点,但序列化器 GroupSerializer 似乎不想默认允许多个值通过。

因此,使用 PUT 请求将值“2”PUT 到 PK 为 1 的分组是成功的。但是,尝试将 ['2','3'] , [2,3] , 2,3'2','3'

通过 View 追溯到实用方法,我发现它是 serializer.is_valid()请求失败,所以这让我认为这是一个 many=True问题,但我不知道使用哪个关系序列化器来解决这个特定的自引用 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.error 的调试错误输出为

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) 及其序列化器进行自引用的?如果是这样,怎么办?

最佳答案

看起来像嵌套序列化的情况。模型应该是 -

class Group(models.Model):
group_id = models.IntegerField(read_only=True)
group_name = models.CharField(max_length=100)
category = models.CharField(max_length=256, required=False)
related_groups = models.ForeignKey('self', required=False, related_name='children')

还有序列化器 -

class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = (
'group_id', 'group_name', 'category', 'related_groups',
)

class NestedGroupSerializer(serializers.ModelSerializer):
children = GroupSerializer(many=True, read_only=True)

class Meta:
model = Group
fields = ('group_id', 'group_name', 'category', 'related_groups', 'children')

然后您可以使用 NestedGroupSerializer 访问所有相关组。

默认情况下,嵌套序列化器是只读的。如果您想支持对嵌套序列化器字段的写入操作,您需要创建 create() 和/或 update() 方法,以便显式指定应如何保存子关系。

希望有帮助。

关于angularjs - Django Rest Framework 与其自身相关的多对多字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39821723/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com