django:断言错误`create()`没有返回对象实例

时间:2019-03-18 22:59:48

标签: django django-rest-framework serializer

我正在使用Django Rest Framework。我有一个现有的数据库(无法对其进行任何更改)。我定义了一个序列化器-没有模型的ReceiptLog,当对ReceiptLog api端点发出post()请求时,应该在TestCaseCommandRun和TestCaseCommandRunResults中创建条目。收据日志在数据库中不存在,我只是将其用作端点来接受组合的有效负载并在基础表中创建条目。 Post()到TestCaseCommandRunResults和TestCaseCommandRun可以独立工作,但是,当我尝试通过ReceiptLog进行发布时,它抛出以下错误

错误回溯:

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/django/views/generic/base.py" in view
  69.             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/generics.py" in post
  192.         return self.create(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
  216.                 '`create()` did not return an object instance.'

Exception Type: AssertionError at /dqf_api/ReceiptLog/
Exception Value: `create()` did not return an object instance.

models.py

class TestCaseCommandRun(models.Model):
   # fields ..Doesn't have id field as the database doesn't have it
   class Meta:
      managed = False
      db_table = 'test_case_command_run'
      unique_together = (('team_name', 'suite_name', 'suite_run_id', 'case_name', 'command_name'),)


class TestCaseCommandRunResults(models.Model):
    # fields ..Doesn't have id field as the database doesn't have it
    class Meta:
        managed = False
        db_table = 'test_case_command_run_results'
        unique_together = (('suite_run_id', 'command_run_id', 'rule_name', 'result_id'),)

views.py

class TestCaseCommandRunViewSet(viewsets.ModelViewSet):
    queryset = models.TestCaseCommandRunViewSet.objects.values(team_name','suite_name','suite_run_id', 'case_name','command_name','command_run_id','run_start','run_end','result','run_status')
    serializer_class = serializers.TestCaseCommandRunViewSet

class TestCaseCommandRunResultsViewSet(viewsets.ModelViewSet):
    queryset = models.TestCaseCommandRunResultsViewSet.objects.values('suite_run_id','command_run_id','rule_name', 'result_id',
                                                           'result','expected_values','actual_values','report_values','extended_values')
    serializer_class = serializers.TestCaseCommandRunResultsViewSet

class ReceiptLogViewSet(CreateAPIView):
    serializer_class = serializers.ReceiptLogSerializer.ReceiptLogSerializerClass

serializers.py

class TestCaseCommandRunResultsViewSet(serializers.ModelSerializer):
    class Meta:
        model = models.TestCaseCommandRunResultsViewSet
        fields = ['suite_run_id','command_run_id','rule_name', 'result_id','result','expected_values','actual_values','report_values','extended_values']

class TestCaseCommandRunSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.TestCaseCommandRunSerializer
        fields = [team_name','suite_name','suite_run_id', 'case_name','command_name','command_run_id','run_start','run_end','result','run_status']

class ReceiptLogSerializerClass(serializers.Serializer):
    team_name = serializers.CharField(max_length=30)
    suite_name = serializers.CharField(max_length=100)
    suite_run_id = serializers.CharField(max_length=50,required=False, allow_blank=True, default=datetime.now().strftime('%Y%m%d%H%M%S'))
    case_name = serializers.CharField(max_length=50)
    command_name = serializers.CharField(max_length=50)
    command_run_id = serializers.CharField(max_length=50,required=False, allow_blank=True, default='Not Applicable')
    run_start = serializers.DateTimeField(default=datetime.now, required=False)
    run_end = serializers.DateTimeField(default=datetime.now, required=False)
    result = serializers.CharField(max_length=10, default='Not Applicable')
    run_status = serializers.CharField(max_length=10)
    rule_name = serializers.CharField( max_length=50, required=False, allow_blank=True,  default='Not Applicable')
    expected_values = serializers.CharField(max_length=200, allow_blank=True)
    actual_values = serializers.CharField(max_length=200, allow_blank=True)
    report_values = serializers.CharField(max_length=200, allow_blank=True)
    extended_values = serializers.CharField(max_length=200, allow_blank=True)

    def create(self, validated_data):
    # command_run_data_list = []
    command_run_results_data_list = []
    raw_data_list = []
    many = isinstance(validated_data, list)
    if many:
        raw_data_list = validated_data
    else:
        raw_data_list.append(validated_data)
    result_id = 1
    for data_row in raw_data_list:
        new_command_run_entry = {
            'team_name': data_row.get('team_name'),
            'suite_name': data_row.get('suite_name'),
            'suite_run_id': data_row.get('suite_run_id'),
            'case_name': data_row.get('case_name'),
            'command_name': data_row.get('command_name'),
            'command_run_id': data_row.get('command_run_id'),
            'run_start': data_row.get('run_start'),
            'run_end': data_row.get('run_end'),
            'result': data_row.get('result'),
            'run_status': data_row.get('run_status')
        }
        command_run_data_list.append(new_command_run_entry)
        new_command_run_result_entry = {
            'suite_run_id': data_row.get('suite_run_id'),
            'command_run_id': data_row.get('command_run_id'),
            'rule_name': data_row.get('rule_name'),
            'result_id': result_id,
            'result': data_row.get('result'),  # PASS or FAIL
            'expected_values': data_row.get('expected_values'),
            'actual_values': data_row.get('actual_values'),
            'report_values': data_row.get('report_values'),
            'extended_values': data_row.get('extended_values'),
        }
        command_run_results_data_list.append(new_command_run_result_entry)
        result_id += 1

    for item in command_run_results_data_list:
        response_run_results = models.TestCaseCommandRunResults.objects.create(**item)

    for item in command_run_data_list:
        response_run = models.TestCaseCommandRun.objects.create(**item)

urls.py

router = routers.DefaultRouter()
router.register(r'test_case_command_runs', views.TestCaseCommandRunViewSet)
router.register(r'test_case_command_run_results', views.TestCaseCommandRunResultsViewSet)
urlpatterns = [
    url(r'^buildInfo', views.build_info),
    url(r'^isActive', views.is_active),
    url(r'^dqf_api/', include(router.urls)),
    url(r'^dqf_api/ReceiptLog/', views.ReceiptLogView.ReceiptLogViewSet.as_view(), name='ReceiptLog')]

非常感谢您的帮助。我是Django和DRF的新手

3 个答案:

答案 0 :(得分:1)

您的序列化程序的create方法必须返回其表示的对象的实例。另外,您不应该在序列化程序内部进行迭代来创建实例,而应该在视图上完成:您要遍历数据,每次迭代都调用序列化程序。

答案 1 :(得分:1)

更新了serializers.py文件,使其包含以下代码

class ReceiptLogSerializerClass(serializers.Serializer):
    #Fields
    def create(self, validated_data):
        raw_data_list = []
        many = isinstance(validated_data, list)
        if many:
            raw_data_list = validated_data
        else:
            raw_data_list.append(validated_data)
        result_id = 1
        for data_row in raw_data_list:
            new_command_run_entry = {
            'team_name': data_row.get('team_name'),
            'suite_name': data_row.get('suite_name'),
            'suite_run_id': data_row.get('suite_run_id'),
            'case_name': data_row.get('case_name'),
            'command_name': data_row.get('command_name'),
            'command_run_id': data_row.get('command_run_id'),
            'run_start': data_row.get('run_start'),
            'run_end': data_row.get('run_end'),
            'result': data_row.get('result'),
            'run_status': data_row.get('run_status')
        }
       response = TestCaseCommandRunSerializer.create(TestCaseCommandRunSerializer(),validated_data= new_command_run_entry)
       new_command_run_result_entry = {
            'suite_run_id': data_row.get('suite_run_id'),
            'command_run_id': data_row.get('command_run_id'),
            'rule_name': data_row.get('rule_name'),
            'result_id': result_id,
            'result': data_row.get('result'),  # PASS or FAIL
            'expected_values': data_row.get('expected_values'),
            'actual_values': data_row.get('actual_values'),
            'report_values': data_row.get('report_values'),
            'extended_values': data_row.get('extended_values'),
        }
        response = TestCaseCommandRunResultsSerializer.create(TestCaseCommandRunResultsSerializer(),validated_data= new_command_run_result_entry)
        logger.info(" new_command_run_result_entry response %s" % response)
        result_id += 1
    return validated_data

我没有正确反序列化数据,因此遇到了多个问题。         返回validated_data 解决了所有错误,现在我可以通过单个API将数据发布到多个模型中。

要在单个API调用中发布多个有效负载,请在ReceiptLogViewSet中的行下方添加

    def get_serializer(self, *args, **kwargs):
        if "data" in kwargs:
            data = kwargs["data"]
        if isinstance(data, list):
            kwargs["many"] = True
    return super(ReceiptLogViewSet, self).get_serializer(*args, **kwargs)

参考:Django rest framework cannot deal with multple objects in model viewset

答案 2 :(得分:0)

序列化器ReceiptLogSerializerClass必须是 ModelSerializer ,而不是序列化器