在Celery任务期间保存对象

时间:2019-02-14 11:29:28

标签: python django django-models

我想在save期间在数据库中Celery task放置一个对象。该对象是导出文件。 Celery任务允许创建它,我想将其存储在表中。

这是我的 models.py

class CeleryExportFile(models.Model):
    name = models.CharField(max_length=100, verbose_name=_('Name of export file'), default='')
    file = models.FileField(upload_to='media/', default='')
    creation_date = models.DateTimeField(verbose_name=_('Creation date'), auto_now_add=True)
    expiration_date = models.DateTimeField(verbose_name=_('Expiration date'))

    def __str__(self):
        return self.file

    class Meta:
        verbose_name = _('Celery Export File')
        verbose_name_plural = _('Celery Export Files')

我有一个Celery tasks.py 文件:

def get_xls_export(self, model="", search_info="", query_params=None):

    app_label = 'app'
    its_fp_or_up_product = False
    query_params = query_params or {}
    obsolete = False
    if query_params.get('obsolete', '') == 'True':
        obsolete = True

    default_sorting_key = ''
    show_date_format = settings.USER_DATE_FORMAT
    if model == "finalproduct" or model == "upstreamproduct":
        its_fp_or_up_product = True
        default_sorting_key = 'manufacturer_name' if model == "finalproduct" else 'releasing_body__short_name'
    if model == "releasebodyinstitution":
        default_sorting_key = 'name'

    model = apps.get_model(app_label=app_label, model_name=model)

    # create a workbook in memory
    output = io.BytesIO()

    book = Workbook(output, {'constant_memory': True})
    sheet = book.add_worksheet('Page 1')
    # Sheet header, first row
    row_num = 0

    columns = model.export_field_excel()
    rows_width_max = {}
    bold_format = book.add_format({'bold': True})
    max_col_width = []

    for col_num in range(len(columns)):
        rows_width_max[col_num] = columns[col_num].__len__()
        sheet.write(row_num, col_num, columns[col_num], bold_format)
        max_col_width.append(len(columns[col_num]) if len(columns[col_num]) > 10 else 10)

    default_sorting = True
    sorting_key = ''
    # Define search get all object or sorted value.
    if search_info != '':
        create_filters = search_info.split(';')
        if create_filters.__len__() == 1:
            if 'sorting' in create_filters[0]:
                default_sorting = False
                sorting_key = create_filters[0].split('=')[1].replace('~', '-')
                search_info = ''
        else:
            for criter in create_filters:
                if 'sorting' in criter:
                    default_sorting = False
                    sorting_key = criter.split('=')[1].replace('~', '-')
                    search_info = search_info.replace(criter, "")
                    search_info = search_info[:-1]

    objects = model.objects.all()

    if not its_fp_or_up_product:
        if obsolete:
            objects = objects.obsolete()
        else:
            objects = objects.active()

    if sorting_key:
        objects = objects.order_by(sorting_key, 'pk')

    if default_sorting:
        objects = objects.order_by(default_sorting_key, 'pk')

    if search_info != '':
        create_filters = search_info.split(';')
        for search_filter in create_filters:
            search_filter = search_filter.split('=')
            try:
                if search_filter[1]:
                    objects = objects.filter(**{search_filter[0]: search_filter[1]})
            except:
                # Crud patch search
                if search_filter[0] == 'q':
                    search_info = search_info.replace('q=', '')
                objects = objects.filter(get_query(search_info, model.get_xls_values_list()))

    rows = objects.values_list(*model.get_xls_values_list())

    for row in rows:
        row_num += 1
        for col_num in range(len(row)):
            # Patch True False for boolean field
            is_bool = False
            if type(row[col_num]) is bool:
                is_bool = True

            if col_num in model.get_date_field_number():
                if row[col_num]:
                    sheet.write(row_num, col_num, row[col_num].strftime(show_date_format))
            else:
                if is_bool:
                    sheet.write(row_num, col_num, 'True' if row[col_num] else 'False')
                else:
                    sheet.write(row_num, col_num, row[col_num])

            if len(str(row[col_num])) > max_col_width[col_num]:
                max_col_width[col_num] = len(str(row[col_num]))

    # AutoFit col
    for col_num in range(len(columns)):
        sheet.set_column(col_num, col_num, max_col_width[col_num] + 1)
    book.close()
    output.seek(0)

    name = str(name + "_" + str(datetime.datetime.now().strftime("%Y_%m_%d_%H_%M_%s")) + '.xlsx')

    CeleryExportFile.save(name=name, file=output, expiration_date=datetime.datetime.now())
    # default_storage.save(name, output)

    try:
        self.send_email(name=name)
    except ConnectionRefusedError as e:
        return ['error_message', _('Error for sending email')]
    return ['success_message', _('Generation of export file is done')]

我遇到了这个问题:

[2019-02-14 12:23:56,151: ERROR/ForkPoolWorker-4] Task app.tasks.get_xls_export[80e7ea2e-4192-4df7-ba05-83a14805225f] raised unexpected: TypeError("save() got an unexpected keyword argument 'name'",)
Traceback (most recent call last):
  File "/home/.pyenv/versions/3.6.2/envs/app/lib/python3.6/site-packages/celery/app/trace.py", line 382, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/home/.pyenv/versions/3.6.2/envs/app/lib/python3.6/site-packages/celery/app/trace.py", line 641, in __protected_call__
    return self.run(*args, **kwargs)
  File "/home/Bureau/Projets/app/src/app/tasks.py", line 151, in get_xls_export
    CeleryExportFile.save(name='test', file=book, expiration_date=datetime.datetime.now())
TypeError: save() got an unexpected keyword argument 'name'

如何将文件保存到数据库中? 我必须将名称,文件,..设置为kwargs,并在我的 models.py 中使用save()创建一个kwargs.pop方法?

1 个答案:

答案 0 :(得分:2)

只需执行以下操作:

celery_export_file = CeleryExportFile(name=name, file=output, expiration_date=datetime.datetime.now())
celery_export_file.save()

或者您可以像这样调用create()方法:

CeleryExportFile.objects.create(name=name, file=output, expiration_date=datetime.datetime.now())