反序列化没有被正确调用,但找不到方法或调用的地方

时间:2015-07-10 16:15:14

标签: python django serialization django-rest-framework

所以我有这个模型:

class CdrSheet(models.Model):
    MONTH_CHOICES = ((1, "January"), (2, "February"), (3, "March"), (4, "April"), (5, "May"), (6, "June"), (7, "July"),
                     (8, "August"), (9, "September"), (10, "October"), (11, "November"), (12, "December"))

    uploaded = models.DateTimeField(auto_now_add=True, blank=False)
    title = models.CharField(max_length=100, blank=True)
    slug = models.SlugField(unique=True)
    report_year = models.IntegerField(default=datetime.datetime.now().year, blank=False, help_text="Requi"
                                                                                                                 "red")
    report_month = models.IntegerField(choices=MONTH_CHOICES, default=1, blank=False, help_text="Required")
    file = models.FileField(max_length=None, blank=False, upload_to=file_name, help_text="CSV files only")
    carrier = models.CharField(max_length=100, blank=False, help_text="Required")
    ani_field = models.CharField(max_length=20, default="ani", blank=True, help_text="Default: 'ani'")
    ani_country_code = models.CharField(max_length=2, default="", blank=True, help_text="If blank, script will assume "
                                                                                        "numbers are internationally "
                                                                                        "formatted")
    dest_field = models.CharField(max_length=20, default="dest", blank=True, help_text="Default: 'dest'")
    dest_country_code = models.CharField(max_length=2, default="", blank=True, help_text="If blank, script will assume "
                                                                                         "numbers are internationally "
                                                                                         "formatted")
    duration_field = models.CharField(max_length=20, blank=True, default="duration", help_text="Default: 'duration'")
    cost_field = models.CharField(max_length=20, blank=True, default="cost", help_text="Default: 'cost'")
    date_field = models.CharField(max_length=20, blank=True, default="date", help_text="Default: 'date'")
    date_format = models.CharField(max_length=20, blank=True, default="%m/%d/%Y", help_text="Please use format "
                                                                                            "specifications shown at "
                                                                                            "http://strftime.org. "
                                                                                            "Default: '%m/%d/%Y'")
    time_field = models.CharField(max_length=20, blank=True, default="time", help_text="Default: 'time'")
    time_format = models.CharField(max_length=20, blank=True, default="%H:%M:%S", help_text="Please use format "
                                                                                            "specifications shown at "
                                                                                            "http://strftime.org. "
                                                                                            "Default: '%H:%M:%S'")

    class Meta:
        ordering = ('uploaded',)

我有这个应该工作的序列化器:

class CdrSheetSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = CdrSheet
        fields = ('pk', 'uploaded', 'title', 'report_year', 'report_month', 'file', 'carrier', 'ani_field',
                  'ani_country_code', 'dest_field', 'dest_country_code', 'duration_field', 'cost_field', 'date_field',
                  'date_format', 'time_field', 'time_format', 'slug')
        read_only_fields = ('pk', 'uploaded', 'slug')

但是,当我尝试在django rest框架中创建对象时,会在rest_framework中的某处抛出一个TypeError,给我这个:

  

在致电TypeError时获得CdrSheet.objects.create()。这可能是因为序列化程序类上的可写字段不是CdrSheet.objects.create()的有效参数。您可能需要将该字段设置为只读,或覆盖CdrSheetSerializer.create()方法以正确处理此字段。   原始异常文本是:deserialize()只需要2个参数(给定1个)。

我对这个神秘的反序列化方法的定义和使用方式感到非常困惑。我找不到任何地方。它是在django源代码中吗?它是在rest-framework代码中,它是一个普通的python方法吗?我不明白为什么它给了我这个错误。任何帮助将不胜感激。

P.S。我确实覆盖了CdrSheet模型的save方法,但它非常大,我不想因为代码量而把所有人都拒之门外。再次感谢!

以下是完整的追溯,请求:

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/viewsets.py" in view
  85.             return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py" in dispatch
  456.             response = self.handle_exception(exc)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py" in dispatch
  453.             response = handler(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/mixins.py" in create
  20.         self.perform_create(serializer)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/mixins.py" in perform_create
  25.         serializer.save()
File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py" in save
  169.             self.instance = self.create(validated_data)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py" in create
  798.             raise TypeError(msg)

Exception Type: TypeError at /cdrs/
Exception Value: Got a `TypeError` when calling `CdrSheet.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `CdrSheet.objects.create()`. You may need to make the field read-only, or override the CdrSheetSerializer.create() method to handle this correctly.
Original exception text was: deserialize() takes exactly 2 arguments (1 given).

这是我的重叠保存方法。它不是那么大,我只是觉得它可能很烦人。所以这就是:

def save(self, *args, **kwargs):
    # Override the save function

    columns = {}
    columns['ANI'] = self.ani_field if self.ani_field else 'ani'
    columns['DEST'] = self.dest_field if self.dest_field else 'dest'
    columns['DURATION'] = self.duration_field if self.duration_field else 'duration'
    columns['COST'] = self.cost_field if self.cost_field else 'cost'
    columns['DATE'] = self.date_field if self.date_field else 'date'
    columns['TIME'] = self.time_field if self.time_field else 'time'

    if not self.pk:
        title = self.title
        self.slug = unique_slugify(title if title else "{0} cdr from {1}{2:02d}"
                                        .format(self.file.name, self.report_year,
                                                self.report_month), self._meta.get_field('slug').max_length, CdrSheet)

    super(CdrSheet, self).save(*args, **kwargs)

    def parse_row(row):
        date_format = self.date_format if self.date_format else '%m/%d/%Y'
        time_format = self.time_format if self.time_format else '%H:%M:%S'

        Cdr.create(report=self.pk,
                   report_datetime="{}{}".format(self.report_year, self.report_month),
                   datetime=datetime.datetime.strptime("{} {}".format(row[columns['DATE']], row[columns['TIME']]),
                                                       "{} {}".format(date_format, time_format)),
                   ani="{}{}".format(self.ani_country_code, row[columns['ANI']]),
                   dest="{}{}".format(self.dest_country_code, row[columns['DEST']]),
                   duration=row[columns['DURATION']],
                   cost=row[columns['COST']])

    filename = self.file.path
    cdr_path = os.path.abspath(filename)

    with open(cdr_path) as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            parse_row(row)

这是我在models.py文件顶部的方法:

@receiver(pre_delete)
def delete_catcher(sender, instance, **kwargs):
    if sender == CdrSheet:
        cdrs = Cdr.objects.filter(report=instance.pk)
        for cdr in cdrs:
            cdr.delete()


def file_name(instance, filename):
    # To get the filename/path for the uploaded csv file
    return '/'.join([str(instance.report_year) + '{0:02d}'.format(instance.report_month), instance.title +
                     os.path.splitext(filename)[1]])


def unique_slugify(string, max_length, obj):
    slug = slugify(string)

    for x in itertools.count(1):
        if not obj.objects.filter(slug=slug).exists():
            break
        slug = "{}-{}".format(slug[:max_length - len(str(x)) - 1], x)
    return slug

我想我找到了错误的来源。调用CdrSheet.objects.create(**validate_data)提出了这个追溯:

Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/viewsets.py" in view
  85.             return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py" in dispatch
  456.             response = self.handle_exception(exc)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py" in dispatch
  453.             response = handler(request, *args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/mixins.py" in create
  20.         self.perform_create(serializer)
File "/usr/local/lib/python2.7/dist-packages/rest_framework/mixins.py" in perform_create
  25.         serializer.save()
File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py" in save
  169.             self.instance = self.create(validated_data)
File "/home/supereman16/PerfectPitchTech/projects/processor_api/sheets/serializers.py" in create
  14.         return CdrSheet.objects.create(**validated_data)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py" in manager_method
  127.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in create
  348.         obj.save(force_insert=True, using=self.db)
File "/home/supereman16/PerfectPitchTech/projects/processor_api/sheets/models.py" in save
  110.                 parse_row(row)
File "/home/supereman16/PerfectPitchTech/projects/processor_api/sheets/models.py" in parse_row
  102.                        cost=row[columns['COST']])
File "/usr/local/lib/python2.7/dist-packages/cassandra/cqlengine/models.py" in create
  603.         return cls.objects.create(**kwargs)
File "/usr/local/lib/python2.7/dist-packages/cassandra/cqlengine/query.py" in create
  713.         return self.model(**kwargs).batch(self._batch).ttl(self._ttl).\
File "/usr/local/lib/python2.7/dist-packages/cassandra/cqlengine/models.py" in __init__
  365.                 value = column.to_python(value)
File "/usr/local/lib/python2.7/dist-packages/cassandra/cqlengine/columns.py" in to_python
  491.             return datetime.utcfromtimestamp(DateType.deserialize(value)).date()

Exception Type: TypeError at /cdrs/
Exception Value: deserialize() takes exactly 2 arguments (1 given)

1 个答案:

答案 0 :(得分:0)

我修好了。这恰好是我的cqlengine模型的问题,以及我试图添加到它的内容。我的模型看起来像这样:

# ...
report_datetime = columns.Date(required=True, primary_key=True)
datetime = columns.DateTime(required=True)
# ...

这些是我的创建调用的参数:

Cdr.create( # ... First few args
    report_datetime="{}{}".format(self.report_year, self.report_month),
    datetime=datetime.datetime.strptime("{} {}".format(row[columns['DATE']], row[columns['TIME']]),
                                        "{} {}".format(date_format, time_format)),
            # ... Last few args )

我试图将日期字段设置为文本值,并抱怨。谢谢一群人!