django - djanga rest 框架:“str”对象没有属性“pk”
问题描述
我正在使用 Django 休息框架。我有一个现有的数据库(无法对其进行任何更改)。我的表 TestSuite 上有复合 pk。当我在 test_suites 上执行 get() 时,它会引发错误 - 'str' object has no attribute 'pk'
。我没有在我的模型中定义 pk ,与 django 一样,我无法定义复合主键。因此,django 使用 'id' 一个自动生成的模型 pk。我无法在我的数据库中添加 id(因为我无法修改数据库)。post() 按预期工作,但是 get() 通过 postman() 以及可浏览的 API 引发错误。
我是 DRF 的新手。任何帮助表示赞赏。
数据库创建语句:
CREATE TABLE `test_suite` (
`team_name` varchar(30) NOT NULL,
`suite_name` varchar(100) NOT NULL,
`description` varchar(200) DEFAULT NULL,
`schedule` varchar(100) DEFAULT NULL,
`email_list_ok` varchar(200) DEFAULT NULL,
`email_list_fail` varchar(200) DEFAULT NULL,
`template_name` varchar(100) NOT NULL,
PRIMARY KEY (`team_name`,`suite_name`),
KEY `fk_test_suite__email_templates` (`template_name`),
CONSTRAINT `fk_test_suite__email_templates` FOREIGN KEY (`template_name`) REFERENCES `email_templates` (`template_name`),
CONSTRAINT `fk_test_suite__team` FOREIGN KEY (`team_name`) REFERENCES `team` (`team_name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
我需要对此表执行 get() 和 post() 。下面是我的模型、序列化程序和视图集。
模型.py
class Team(models.Model):
team_name = models.CharField(primary_key=True, max_length=30)
description = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = False
db_table = 'team'
class TestSuite(models.Model):
team_name = models.ForeignKey(Team, on_delete=models.DO_NOTHING, db_column='team_name')
suite_name = models.CharField(max_length=100)
description = models.CharField(max_length=200, blank=True, null=True)
schedule = models.CharField(max_length=100, blank=True, null=True)
email_list_ok = models.CharField(max_length=200, blank=True, null=True)
email_list_fail = models.CharField(max_length=200, blank=True, null=True)
template_name = models.ForeignKey(EmailTemplates, on_delete=models.DO_NOTHING, db_column='template_name')
class Meta:
managed = False
db_table = 'test_suite'
unique_together = (('team_name', 'suite_name'),)
视图.py
class TestSuiteViewSet(viewsets.ModelViewSet):
queryset = models.TestSuite.objects.values('team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name')
serializer_class = serializers.TestSuiteSerializer
class TeamViewSet(viewsets.ModelViewSet):
queryset = models.Team.objects.all()
serializer_class = serializers.TeamSerializer
序列化程序.py
class TestSuiteSerializer(serializers.ModelSerializer):
class Meta:
model = models.TestSuite
fields = ['team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name']
错误回溯:
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py" in inner
35. response = get_response(request)
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.6/contextlib.py" in inner
52. return func(*args, **kwds)
File "/usr/local/lib/python3.6/dist-packages/django/views/decorators/csrf.py" in wrapped_view
54. return view_func(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/viewsets.py" in view
116. return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
495. response = self.handle_exception(exc)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in handle_exception
455. self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
492. response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in list
48. return Response(serializer.data)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in data
768. ret = super(ListSerializer, self).data
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in data
262. self._data = self.to_representation(self.instance)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in to_representation
686. self.child.to_representation(item) for item in iterable
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in <listcomp>
686. self.child.to_representation(item) for item in iterable
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in to_representation
530. ret[field.field_name] = field.to_representation(attribute)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/relations.py" in to_representation
272. return value.pk
Exception Type: AttributeError at /dqf_api/test_suites/
Exception Value: 'str' object has no attribute 'pk'
网址.py
router = routers.DefaultRouter()
router.register(r'teams', views.TeamViewSet)
router.register(r'test_suites', views.TestSuiteViewSet)
urlpatterns = [ url(r'^dqf_api/', include(router.urls))]
编辑:
我能够通过将以下代码添加到我的 serializers.py 来解决 get() 但是,现在我的 post() 不起作用 -ValueError at /dqf_api/test_suites/
Cannot assign "'ede'": "TestSuiteModel.team_name" must be a "Team" instance.
def to_representation(self, obj):
return {
'team_name': obj.get('team_name'),
'suite_name': obj.get('suite_name'),
'description': obj.get('description'),
'schedule': obj.get('schedule'),
'email_list_ok': obj.get('email_list_ok'),
'email_list_fail': obj.get('email_list_fail'),
'template_name': obj.get('template_name'),
}
def to_internal_value(self, data):
return {
'team_name': data.get('team_name'),
'suite_name': data.get('suite_name'),
'description': data.get('description'),
'schedule': data.get('schedule'),
'email_list_ok': data.get('email_list_ok'),
'email_list_fail': data.get('email_list_fail'),
'template_name': data.get('template_name'),
}
错误回溯:
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py" in inner
35. response = get_response(request)
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.6/contextlib.py" in inner
52. return func(*args, **kwds)
File "/usr/local/lib/python3.6/dist-packages/django/views/decorators/csrf.py" in wrapped_view
54. return view_func(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/viewsets.py" in view
116. return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
495. response = self.handle_exception(exc)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in handle_exception
455. self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/views.py" in dispatch
492. response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in create
21. self.perform_create(serializer)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/mixins.py" in perform_create
26. serializer.save()
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in save
214. self.instance = self.create(validated_data)
File "/usr/local/lib/python3.6/dist-packages/rest_framework/serializers.py" in create
943. instance = ModelClass._default_manager.create(**validated_data)
File "/usr/local/lib/python3.6/dist-packages/django/db/models/manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/django/db/models/query.py" in create
415. obj = self.model(**kwargs)
File "/usr/local/lib/python3.6/dist-packages/django/db/models/base.py" in __init__
477. _setattr(self, field.name, rel_obj)
File "/usr/local/lib/python3.6/dist-packages/django/db/models/fields/related_descriptors.py" in __set__
197. self.field.remote_field.model._meta.object_name,
Exception Type: ValueError at /dqf_api/test_suites/
Exception Value: Cannot assign "'ede'": "TestSuiteModel.team_name" must be a "Team" instance.
解决方案
外键关系的序列化和反序列化存在问题。我通过将以下代码添加到 serializers.py 来修复它
class TestSuiteSerializer(serializers.ModelSerializer):
class Meta:
model = models.TestSuiteModel
fields = ['team_name','suite_name', 'description','schedule','email_list_ok','email_list_fail','template_name']
def to_representation(self, obj):
if isinstance(obj, dict): # get methods
return obj
else:
self.fields['team_name'] = TeamSerializer()
self.fields['template_name'] = EmailTemplatesSerializer()
return super(TestSuiteSerializer, self).to_representation(obj)
推荐阅读
- kubernetes - 如何将 PodSecurityPolicy 角色绑定到组?
- python - 在面板数据上建立回归模型的任何有效方法?
- php - 如何构建这样的无键数组?
- css - 如何更改材质ui表中所选行的文本颜色
- php - 在 Azure Cosmos 中跨多个集合查询记录
- sql - 通过 SQL EXTRACTVALUE 命名空间 XML 的 XPath 失败?
- c++ - cURL setopt CONNECTTIMEOUT 与 TIMEOUT
- xamarin.forms - 如何以编程方式从 Android 设备中检索已安装的证书(Xamarin)
- android - 如何正确地将数据从 Android 发送到 Flutter?
- vue.js - 调用 Vuex 突变需要太多时间来加载内容和突变