Django 数据库填充与 AttributeError:‘QuerySet’ 对象没有属性 <custom_model_method>
我在做一个简单的集成测试时遇到了这个错误。这个Django应用叫做 storageadmin
,里面有一个模型叫 Disk
,还有一个自定义的方法叫 pool_name
。我在使用South和Django REST框架,并且在 settings.py
中设置了 SOUTH_TESTS_MIGRATE = False
。
这个数据文件是通过以下命令创建的。在执行 dumpdata
之前,默认数据库里已经有了一些模型数据,足够用来测试。
./bin/django dumpdata storageadmin oauth2_provider auth.User --indent=2 > src/rockstor/storageadmin/fixtures/storageadmin.json
错误和下面这个模型有关:
class Disk(models.Model):
pool = models.ForeignKey(Pool, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=10, unique=True)
def pool_name(self, *args, **kwargs):
try:
return self.pool.name
except:
return None
class Meta:
app_label = 'storageadmin'
有一个序列化器在视图中用来发送响应。
class DiskInfoSerializer(serializers.ModelSerializer):
pool_name = serializers.CharField(source='pool_name')
class Meta:
model = Disk
这个视图返回的响应是这样的:
ds = DiskInfoSerializer(Disk.objects.all())
return Response(ds.data)
编辑:根据正确答案的提示,问题出在上面的视图中。我使用的是一个非常旧的DRF版本(2.1.15),而当前测试的版本(2.4.3)需要 ds = DiskInfoSerializer(Disk.objects.all(), many=True)
触发错误的简单测试案例是:
class DiskTests(APITestCase):
fixtures = ['storageadmin.json']
BASE_URL = '/api/disks/scan'
def test_disk_scan(self):
self.client.login(username='admin', password='admin')
response = self.client.post(self.BASE_URL, data=None, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
最后,错误信息是:
File "/opt/rock-dep/src/rockstor/storageadmin/views/disk.py", line 88, in _scan
return Response(ds.data)
File "/opt/rock-dep/eggs/djangorestframework-2.4.3-py2.7.egg/rest_framework /serializers.py", line 572, in data
self._data = self.to_native(obj)
File "/opt/rock-dep/eggs/djangorestframework-2.4.3-py2.7.egg/rest_framework/serializers.py", line 351, in to_native
value = field.field_to_native(obj, field_name)
File "/opt/rock-dep/eggs/djangorestframework-2.4.3-py2.7.egg/rest_framework/fields.py", line 336, in field_to_native
return super(WritableField, self).field_to_native(obj, field_name)
File "/opt/rock-dep/eggs/djangorestframework-2.4.3-py2.7.egg/rest_framework/fields.py", line 207, in field_to_native
value = get_component(value, component)
File "/opt/rock-dep/eggs/djangorestframework-2.4.3-py2.7.egg/rest_framework/fields.py", line 58, in get_component
val = getattr(obj, attr_name)
AttributeError: 'QuerySet' object has no attribute 'pool_name'
代码本身是没问题的,问题只是在测试的时候出现。
1 个回答
8
就像错误信息所说的,你传递了一个查询集,但没有告诉DRF(Django Rest Framework)你在做什么。你需要加上 many=True
这个参数:
ds = DiskInfoSerializer(Disk.objects.all(), many=True)