Create a Celery task with Django

116 views
Skip to first unread message

valentin jungbluth

unread,
Feb 13, 2019, 6:34:17 AM2/13/19
to Django users
Hello guys,

I'm working on my Django project and I need to integrate Celery to do something.
I'm using Django 1.11.20.

My context :

I have a template page with a search form. Once you did a search, it returns a table with search results.
It's possible to export to .xls format with/without search.

There are 2 possibilities :

  • If user wants to export less than 70.000 objects, the export creates an HttpResponse with download link.
  • If user wants to export more than 70.000 objects, a Celery task has to be initiate, it creates the file, save it into the MEDIA folder and user gets an email with expirable download link.
I'm trying to implement this second part.

The check is done on template page with number of results according to the search part. 
If < 70.000 objects, export button calls export_xls() function, else it calls the Celery task get_xls_export()

HTML Template file :

{% if item_count > 0 and item_count < 70000 %}
    {% if search_info_str %}
      <a title="Print" href="{% url print_link model='finalproduct' search_info=search_info_str %}" class="button btn btn-default print_items"><span class="glyphicon glyphicon-print"></span></a>
      <a title="Export to Excel" class="button btn btn-default" href="{% url 'ocabr:export-xls' model=model search_info=search_info_str %}"><span class="glyphicon glyphicon-export"></span></a>
    {% else %}
      <a title="Print" href="{% url print_link model='finalproduct' %}" class="button btn btn-default print_items"><span class="glyphicon glyphicon-print"></span></a>
      <a title="Export to Excel" class="button btn btn-default" href="{% url 'ocabr:export-xls' model=model %}"><span class="glyphicon glyphicon-export"></span></a>
    {% endif %}
{% else %}
    {% if search_info_str %}
      <a title="Print" href="{% url print_link model='finalproduct' search_info=search_info_str %}" class="button btn btn-default print_items"><span class="glyphicon glyphicon-print"></span></a>
      <a title="Export to Excel" name="export" value="export" class="button btn btn-default" href="{% url 'ocabr:cron_export' model=model search_info=search_info_str %}"><span class="glyphicon glyphicon-export"></span></a>
    {% else %}
      <a title="Print" href="{% url print_link model='finalproduct' %}" class="button btn btn-default print_items"><span class="glyphicon glyphicon-print"></span></a>
      <a title="Export to Excel" name="export" value="export" class="button btn btn-default" href="{% url 'ocabr:cron_export' model=model %}"><span class="glyphicon glyphicon-export"></span></a>
    {% endif %}
{% endif %}

This part calls the right function depending on search result.

Case 1 : Less than 70.000 objects

The view associated to the previous HTML template is :

class FinalProductListView(PermissionRequiredMixin, EdqmListSearchView):

    model = FinalProduct
    page_title = _('Final Products')
    default_sort_params = ('manufacturer_name', 'asc')
    sort_params = ['pk']

    create_link = 'ocabr:finalproduct-add'
    update_link = 'ocabr:finalproduct-edit'
    delete_link = 'ocabr:finalproduct-delete'
    view_link = 'ocabr:finalproduct-view'
    print_link = 'ocabr:print-object'

    permission_required = 'ocabr.view_finalproduct'

    template_name = 'ocabr/final_product/final_product_search.html'

    paginate_by = getattr(PaginationMixin, 'paginate_by', None)
    headers = {
        'releasing_body__short_name': 'Releasing Body/Institution',
        'is_withdrawn': 'Is nullified',
    }

    # Configuration of fields
    fields = ['manufacturer_name', 'releasing_body__short_name', 'product_trade_name', 'pheur_name', 'name', 'final_bulk',
              'decision', 'date_decision', 'is_withdrawn', 'member_state']

    def get_queryset(self):
        queryset = super(FinalProductListView, self).get_queryset()

        date_format = settings.USER_DATE_FORMAT
        # Add filter from search form.
        if 'mah' in self.request.GET:
            if self.request.GET['mah'] != '':
                queryset = queryset.filter(mah__icontains=self.request.GET['mah'].strip())
        if 'releasing_body' in self.request.GET:
            if self.request.GET['releasing_body']:
                queryset = queryset.filter(releasing_body__id=int(self.request.GET['releasing_body']))
        if 'trade_name' in self.request.GET:
            if self.request.GET['trade_name'] != '':
                queryset = queryset.filter(product_trade_name__icontains=self.request.GET['trade_name'].strip())
        if 'member_state' in self.request.GET:
            if self.request.GET['member_state']:
                queryset = queryset.filter(member_state__id=int(self.request.GET['member_state']))
        if 'pheur_name' in self.request.GET:
            if self.request.GET['pheur_name'] != '':
                queryset = queryset.filter(pheur_name__id=self.request.GET['pheur_name'])
        if 'decision' in self.request.GET:
            if self.request.GET['decision']:
                queryset = queryset.filter(decision__id=int(self.request.GET['decision']))
        if 'final_bulk_num' in self.request.GET:
            if self.request.GET['final_bulk_num'] != '':
                queryset = queryset.filter(final_bulk__icontains=self.request.GET['final_bulk_num'].strip())
        if 'domain' in self.request.GET:
            if self.request.GET['domain']:
                queryset = queryset.filter(domain__id=int(self.request.GET['domain']))
        if 'manufacturer_name' in self.request.GET:
            if self.request.GET['manufacturer_name'] != '':
                queryset = queryset.filter(manufacturer_name__id=self.request.GET['manufacturer_name'])
        if 'date_from' in self.request.GET and 'date_to' in self.request.GET:
            if self.request.GET['date_from'] and not self.request.GET['date_to']:
                try:
                    queryset = queryset.filter(date_decision__gte=Utils.filter_date_format(self.request.GET['date_from'], date_format))
                except:
                    pass
            if not self.request.GET['date_from'] and self.request.GET['date_to']:
                try:
                    queryset = queryset.filter(date_decision__lte=Utils.filter_date_format(self.request.GET['date_to'], date_format))
                except:
                    pass
            if self.request.GET['date_from'] and self.request.GET['date_to']:
                try:
                    queryset = queryset.filter(date_decision__range=(Utils.filter_date_format(self.request.GET['date_from'], date_format), Utils.filter_date_format(self.request.GET['date_to'], date_format)))
                except:
                    pass

        if 'name' in self.request.GET:
            if self.request.GET['name'] != '':
                queryset = queryset.filter(name__icontains=self.request.GET['name'].strip())
        if 'eu_cert_n' in self.request.GET:
            if self.request.GET['eu_cert_n'] != '':
                queryset = queryset.filter(eu_cert_n__icontains=self.request.GET['eu_cert_n'].strip())
        if 'status' in self.request.GET:
            if self.request.GET['status'] != '':
                queryset = queryset.filter(status_final_product__icontains=self.request.GET['status'].strip())
        if 'upstream_code_product' in self.request.GET:
            if self.request.GET['upstream_code_product'] != '':
                queryset = queryset.filter(upstream_products__name__icontains=self.request.GET['upstream_code_product'].strip())
        if 'certificate_nullified' in self.request.GET:
            if self.request.GET['certificate_nullified'] != '' and self.request.GET['certificate_nullified'] != 'both':
                queryset = queryset.filter(
                    is_withdrawn__icontains='t' if self.request.GET['certificate_nullified'] == 'True' else 'f')

        return queryset

    def get_context_data(self, **kwargs):
        """ Update the context data with query_string."""
        context = super(EdqmListSearchView, self).get_context_data(**kwargs)
        context['total_records'] = self.get_total_count()
        # Create or Update
        if 'certificate_nullified' in self.request.GET:
            form = FinalProductSearchForm(data=self.request.GET, user=self.request.user)
        else:
            form = FinalProductSearchForm(user=self.request.user, initial={'certificate_nullified': 'both'})

        if not self.page_title:
            self.page_title = _("List of ") + str(self.model._meta.verbose_name_plural)

        # Check perms
        if 'add' in self.model._meta.default_permissions and not self.request.user.has_perm(self.model._meta.app_label + '.add_' + self.model._meta.model_name):
            self.create_link = None
        if 'change' in self.model._meta.default_permissions and not self.request.user.has_perm(self.model._meta.app_label + '.change_' + self.model._meta.model_name):
            self.update_link = None
        if 'delete' in self.model._meta.default_permissions and not self.request.user.has_perm(self.model._meta.app_label + '.delete_' + self.model._meta.model_name):
            self.delete_link = None

        # Send id to print info or excel.
        search_text = ""
        already_sorted = False
        if 'csrfmiddlewaretoken' in self.request.GET:
            # Log search form
            Utils.log_search_form(self, 'Final product')

            search_form_info = [str(info) + '=' + self.request.GET[info] for info in self.request.GET if self.request.GET[info] != '' and info != 'csrfmiddlewaretoken' and self.request.GET[info] != 'both' and info != 'page']
            is_date_to = False
            is_date_from = False
            for date_info in search_form_info:
                if 'date_from' in date_info:
                    is_date_from = True
                if 'date_to' in date_info:
                    is_date_to = True
            is_range_date = True if is_date_to and is_date_from else False
            d1 = ''
            d2 = ''
            for compute_txt in search_form_info:

                # Change filter name.
                if 'mah' in compute_txt:
                    compute_txt = compute_txt.replace('mah', 'mah__contains')
                elif 'sorting' in compute_txt:
                    already_sorted = True
                elif 'releasing_body' in compute_txt:
                    compute_txt = compute_txt.replace('releasing_body', 'releasing_body__id')
                elif 'trade_name' in compute_txt:
                    compute_txt = compute_txt.replace('trade_name', 'product_trade_name__icontains')
                elif 'member_state' in compute_txt:
                    compute_txt = compute_txt.replace('member_state', 'member_state__id')
                elif 'pheur_name' in compute_txt:
                    compute_txt = compute_txt.replace('pheur_name', 'pheur_name__id')
                elif 'decision' in compute_txt:
                    compute_txt = compute_txt.replace('decision', 'decision__id')
                elif 'final_bulk_num' in compute_txt:
                    compute_txt = compute_txt.replace('final_bulk_num', 'final_bulk__icontains')
                elif 'domain' in compute_txt:
                    compute_txt = compute_txt.replace('domain', 'domain__id')
                elif 'manufacturer_name' in compute_txt:
                    compute_txt = compute_txt.replace('manufacturer_name', 'manufacturer_name__id')
                elif 'name' in compute_txt:
                    compute_txt = compute_txt.replace('name', 'name__icontains')
                elif 'eu_cert_n' in compute_txt:
                    compute_txt = compute_txt.replace('eu_cert_n', 'eu_cert_n__icontains')
                elif 'status' in compute_txt:
                    compute_txt = compute_txt.replace('status', 'status_final_product__icontains')
                elif 'upstream_code_product' in compute_txt:
                    compute_txt = compute_txt.replace('upstream_code_product', 'upstream_products__name__icontains')
                elif 'certificate_nullified' in compute_txt:
                    compute_txt = compute_txt.replace('certificate_nullified', 'is_withdrawn__icontains')
                    if 'True' in compute_txt:
                        compute_txt = compute_txt.replace('True', 't')
                    else:
                        compute_txt = compute_txt.replace('False', 'f')

                date_format = settings.USER_DATE_FORMAT
                if not is_range_date:
                    if 'date_from' in compute_txt and is_date_from and not is_date_to:
                        text_to_replace = compute_txt.split('=')[1]
                        try:
                            text_to_replace = Utils.change_date_format(
                                datetime.datetime.strptime(text_to_replace, date_format),
                                date_format).replace('/', '-')
                        except ValueError:
                            pass
                        compute_txt = compute_txt.replace(compute_txt.split('=')[1], text_to_replace)
                        compute_txt = compute_txt.replace('date_from', 'date_decision__gte')
                    if 'date_to' in compute_txt and not is_date_from and is_date_to:
                        text_to_replace = compute_txt.split('=')[1]
                        try:
                            text_to_replace = Utils.change_date_format(datetime.datetime.strptime(text_to_replace, date_format), date_format).replace('/','-')
                        except ValueError:
                            pass
                        compute_txt = compute_txt.replace(compute_txt.split('=')[1], text_to_replace)
                        compute_txt = compute_txt.replace('date_to', 'date_decision__lte')
                else:
                    if 'date_from' in compute_txt:
                        text_to_replace = compute_txt.split('=')[1]
                        try:
                            text_to_replace = Utils.change_date_format(
                                datetime.datetime.strptime(text_to_replace, date_format),
                                date_format).replace('/', '-')
                        except ValueError:
                            pass
                        d1 = text_to_replace.replace(compute_txt.split('=')[1], text_to_replace)
                        continue
                    if 'date_to' in compute_txt:
                        text_to_replace = compute_txt.split('=')[1]
                        try:
                            text_to_replace = Utils.change_date_format(datetime.datetime.strptime(text_to_replace, date_format), date_format).replace('/','-')
                        except ValueError:
                            pass
                        d2 = text_to_replace.replace(compute_txt.split('=')[1], text_to_replace)
                        continue
                if d1 and d2:
                    search_text += 'date_decision__gte=' + d1 + ';date_decision__lte=' + d2 + ';'
                    d1 = ''
                    d2 = ''

                search_text += compute_txt + ';'
            if search_text:
                search_text = search_text[:-1]

        # Sorting patch
        if not already_sorted:
            if 'sorting' in self.request.GET and search_text == '':
                search_text = 'sorting=' + self.request.GET['sorting']

        context.update({
            'title': self.page_title,
            'fields': self.fields,
            'labels': self.get_labels(),
            'view_link': self.view_link,
            'create_link': self.create_link,
            'update_link': self.update_link,
            'delete_link': self.delete_link,
            'search_link': self.search_link,
            'export_links': self.export_links,
            'model': str(self.model._meta.model_name),
            'search_form': form,
            'item_count': self.object_list.count(),
            'print_link': self.print_link,
            'search_info_str': search_text,
            'limit_print_search': settings.LIMIT_PRINT_SEARCH

        })

        if not context.get('is_paginated', False):
            return context

        # Update paginator range
        paginator = context.get('paginator')
        num_pages = paginator.num_pages

        current_page = context.get('page_obj')
        page_no = current_page.number

        if num_pages <= 10 or page_no <= 5:  # case 1 and 2
            pages = [x for x in range(1, min(num_pages + 1, 11))]
        elif page_no > num_pages - 4:  # case 4
            pages = [x for x in range(num_pages - 9, num_pages + 1)]
        else:  # case 3
            pages = [x for x in range(page_no - 5, page_no + 5)]

        context.update({'pages': pages})
        return context


In my template, I have a function export_xls() called when user press "Export" button :

class ExportOCABR(View):

    def export_xls(self, model="", search_info=""):
        app_label = 'ocabr'
        its_fp_or_up_product = False
        obsolete = False
        if self.GET.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())
        # Part which export file directly if less than 70.000 entries else create file with download link

        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()

        # construct response
        output.seek(0)
        name = 'Obsolete' if obsolete else ''
        name += str(model._meta.verbose_name_plural)
        response = HttpResponse(output.read(),
                                content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
        response['Content-Disposition'] = 'attachment; filename="' + name + '.xlsx"'

        return response

The url file looks like :

app_name = 'ocabr'


urlpatterns
= [

# Final Product
    url
(r'^finalproduct/list/$', FinalProductListView.as_view(), name='finalproduct-list'),

# Excel export list
    url
(r'export/xls/(?P<model>[-\w]+)/$', ExportOCABR.export_xls, name='export-xls'),
    url
(r'export/xls/(?P<model>[-\w]+)/(?P<search_info>.*)/$', ExportOCABR.export_xls, name='export-xls'),
]


Case 2 : More than 70.000 objects

I have a tasks.py file :

@shared_task(bind=True, time_limit=3600, soft_time_limit=3600)
def get_xls_export(self, model="", search_info=""):
    app_label = 'ocabr'
    its_fp_or_up_product = False
    obsolete = False
    if self.GET.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())
    # Part which export file directly if less than 70.000 entries else create file with download link

    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 = 'Obsolete' if obsolete else ''
    name += str(model._meta.verbose_name_plural)

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

    # Send mail to django admin
    receiver = settings.CRON_RECEIVER_MESSAGE
    message = "Hello, \n \n" \
              "This is an automatically generated e-mail. \n \n " \
              "On " + str(
        datetime.now()) + " with export file " + name + " available there : " + settings.MEDIA_ROOT + "/" + name

    try:
        send_mail(
            '[TEST database] Export file generated by OCABR',
            message, 'nor...@test.fr',
            receiver)
    except ConnectionRefusedError as e:
        return ['error_message', _('Error for sending email')]
    return ['success_message', _('Generation of export file is done')]

It's similar than export_xls() function, but the end is a bit different. Because I don't create an HttpResponse, but I save the file in MEDIA folder and send an email to user.

My question :

How and where I can create a get_xls_export.delay() when user click on the export button for more than 70.000 objects ? How I can call it from urls.py file ?

Andréas Kühne

unread,
Feb 13, 2019, 9:13:47 AM2/13/19
to django...@googlegroups.com
Hi,

FIrst of all - try to put all the code that is the same for both calls into one method. This way you won't get any problems with that in the future when you need to update the produced excel file. You can actually use the same method in both cases because if you call the method WITHOUT delay() on it, it will be called like a normal method.

To answer your question - all you need to do is have a view that calls the get_xls_export.delay() task. What I would do is I would put all of the code for the selection of which export to use into a view class. Then if the count is less than 70000 I would call the standard export without celery and if it's more than 70000 I would call the delayed function. So your View could contain something like this:

def get():
  if count < 70000:
     exported_file = export_xls()
  else:
     export_xls.delay()


Or something like that (this is just pseudocode :-))

Regards

Andréas


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/da79f356-6164-4c27-bfa2-a918d474a22e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

C. Kirby

unread,
Feb 13, 2019, 10:02:37 AM2/13/19
to Django users
Not directly relevant to your celery question, but I would like to point you to a project of mine - https://django-modelqueryform.readthedocs.io/en/latest/ It lets you build search form that generates complex Q objects. It would replace a lot of you GET field checking and filtering on that view, and I  think make it much more maintainable.

valentin jungbluth

unread,
Feb 13, 2019, 10:53:05 AM2/13/19
to Django users
Thank you Andréas !

I understand your comment, but it could be possible to illustrate it with my code ? I spent 1 week and up to now I don't find any way to solve my issue and execute my Celery task :/

Luis Zárate

unread,
Feb 13, 2019, 4:12:58 PM2/13/19
to django...@googlegroups.com
As Andreas suggest I try to create a function that receive a file object and save the excel content there, Django response works like a file so when you have a less than 70000 then pass the http response and change the headers.  With celery you can store your firters on str as json file and pass to celery delay, then create a temporary file and pass to the excel function with the filters decoded.

Django support Media Fields, so you can create a special file and add to a model and send to a view that check and return de media url.  Also important to delete the file after a period of time.


El miércoles, 13 de febrero de 2019, valentin jungbluth <valent...@gmail.com> escribió:
> Thank you Andréas !
>
> I understand your comment, but it could be possible to illustrate it with my code ? I spent 1 week and up to now I don't find any way to solve my issue and execute my Celery task :/
>
> --
> You received this message because you are subscribed to the Google Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c15b2681-a630-4691-960d-2897f914a553%40googlegroups.com.

> For more options, visit https://groups.google.com/d/optout.
>

--
"La utopía sirve para caminar" Fernando Birri



Luis Zárate

unread,
Feb 13, 2019, 4:14:25 PM2/13/19
to django...@googlegroups.com
See http://django.pyexcel.org/en/latest/

Clean code could be made with this library.


El miércoles, 13 de febrero de 2019, valentin jungbluth <valent...@gmail.com> escribió:
> Thank you Andréas !
>
> I understand your comment, but it could be possible to illustrate it with my code ? I spent 1 week and up to now I don't find any way to solve my issue and execute my Celery task :/
>
Reply all
Reply to author
Forward
0 new messages