python - 禁止 Django 直接分配到多对多集合的反面。使用 .set()
问题描述
我有两个模型,StudyConditions
和studies
,并且在研究中声明了两者之间的多对多关系。我正在努力创造新的条件StudyConditionViewSet
并将它们与研究联系起来。使用下面的 JSON 对象执行发布请求时,我收到错误 Direct assignment to the reverse side of a many-to-many set is disabled 。使用 .set()。这是不可能的,即我只能在 my 中执行此操作StudyViewSet
,还是我缺少/误解了什么?关于这个具体案例,我看到的问题并不多。我已经尝试了 study_obj.conditions.add(new_condition) 和 new_condition.studies.add(study_obj),将条件添加到第一个研究中,并将研究添加到第二个中的条件。我也尝试过使用 set,但没有成功。
编辑: 我很笨,从一个教程中复制并粘贴了一些错误的代码,我的视图中有 StudentSerializer 而不是 StudyConditionSerializer,但这看起来不是问题,仍然出现错误。
{
"name": "Post w/ studies",
"studies": [
{
"id": "1"
},
{
"id": "2"
}
]
}
models.py
class Study(models.Model):
featured = models.BooleanField(default=False)
conditions = models.ManyToManyField('StudyCondition', related_name='studies', db_table='Study_Condition')
class Meta:
db_table = 'Study'
class StudyCondition(models.Model):
name = models.TextField(null=False)
class Meta:
db_table = 'Condition'
views.py
class StudyConditionViewSet(viewsets.ViewSet):
def list(self, request):
queryset = StudyCondition.objects.all()
result = StudyConditionSerializer(queryset, many=True)
if result:
return Response(result.data)
else:
return Response(data=result.data, status=200)
def retrieve(self, request, pk=None):
queryset = StudyCondition.objects.all()
condition = get_object_or_404(queryset, pk=pk)
result = StudyConditionSerializer(condition)
return Response(result.data)
def create(self, request):
data = request.data
new_condition= StudyCondition.objects.create(**data)
new_condition.save()
for study in data["studies"]:
study_obj = Study.objects.get(id=study["id"])
study_obj.conditions.add(new_condition)
# new_condition.studies.add(study_obj)
study_ser = StudyConditionSerializer(new_condition)
if study_ser.is_valid():
return Response(data=study_ser.data, status=201)
else:
return Response(data=study_ser.errors, status=409)
serializers.py
class StudyConditionSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(label='conditionID', required=False)
name = serializers.CharField()
studies = serializers.SerializerMethodField()
class Meta:
model = StudyCondition
fields = ['id', 'name', 'studies']
def to_representation(self, instance: StudyCondition) -> dict:
ret = super().to_representation(instance)
return ret
def get_queryset(self) -> QuerySet:
qs = StudyCondition.objects.all()
return qs
def create(self, validated_data: dict) -> StudyCondition:
return StudyCondition.objects.create(**validated_data)
def get_studies(self, obj):
studies = obj.studies.all()
response = StudyListMiscSerializer(studies, many=True).data
return response
Traceback
Environment:
Request Method: POST
Request URL: http://localhost:8000/api/studies/conditions/
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/studies/views.py", line 112, in create
new_condition= StudyCondition.objects.create(**data)
File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 451, in create
obj = self.model(**kwargs)
File "/usr/local/lib/python3.10/site-packages/django/db/models/base.py", line 498, in __init__
_setattr(self, prop, kwargs[prop])
File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 545, in __set__
raise TypeError(
Exception Type: TypeError at /api/studies/conditions/
Exception Value: Direct assignment to the reverse side of a many-to-many set is prohibited. Use studies.set() instead.
解决方案
根据您的回溯,问题现在很清楚了。request.data
这studies
就是它失败的原因StudyCondition.objects.create(**data)
。所以要修复,只需在创建StudyCondition
.
就像是:
def create(self, request):
data = request.data
studies = data.pop('studies')
new_condition = StudyCondition.objects.create(**data)
new_condition.save()
for study in studies:
...
推荐阅读
- apache-spark - Hbase 过滤特定行
- python - 我可以使用 python 循环遍历多个 excel 文件并将单个工作表添加到主工作簿吗?
- bash - 如果一列中的值包含连续数字并且所有其他列匹配,如何合并行
- java - Android XML-Java 更改首选项的背景颜色
- ios - Xcode Storyboard:根据屏幕大小重新调整按钮大小
- html - 在 CSS 中使图像适合 flexbox 容器
- reactjs - 默认情况下显示第一个 React-leaflet 弹出窗口
- java - 使用 Java 对 API 进行 HTTPS 调用
- image-processing - 只有在整个对象完全在感兴趣区域内之后,如何放置边界框?
- http - 为单个 HTTP 请求返回多个文件的最佳实践?