Tivix / django-cron

Write cron business logic as a Python class and let this app do the rest! It enables Django projects to schedule cron tasks, tracks their success / failures, manages contention (via a cache) etc. Basically takes care of all the boring work for you :-)
www.tivix.com
MIT License
900 stars 193 forks source link

Error 500 on sorting by duration time on admin panel #86

Closed dorianamouroux closed 2 years ago

dorianamouroux commented 8 years ago

Hi,

I'm using Django_cron and I want to know what are the longest duration time of my tasks. On the admin panel, I want to sort by duration time and when I do, I got a 500 errors as below :

Environment:

Request Method: GET
Request URL: http://localhost:8000/admin/django_cron/cronjoblog/?o=4.-2

Django Version: 1.8
Python Version: 3.5.1
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'django.contrib.gis',
 'django_extensions',
 'django_markwhat',
 'django_markdown',
 'jsonify',
 'leaflet',
 'waliki',
 'waliki.git',
 'waliki.attachments',
 'waliki.togetherjs',
 'corsheaders',
 'mail_templated',
 'notifications',
 'import_export',
 'django_cron',
 'stdimage',
 'ttn',
 'wiki',
 'debug_toolbar')
Installed Middleware:
('debug_toolbar.middleware.DebugToolbarMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',)

Traceback:
File "/usr/local/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.5/site-packages/django/contrib/admin/options.py" in wrapper
  616.                 return self.admin_site.admin_view(view)(*args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/contrib/admin/sites.py" in inner
  233.             return view(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapper
  34.             return bound_func(*args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/utils/decorators.py" in _wrapped_view
  110.                     response = view_func(request, *args, **kwargs)
File "/usr/local/lib/python3.5/site-packages/django/utils/decorators.py" in bound_func
  30.                 return func.__get__(self, type(self))(*args2, **kwargs2)
File "/usr/local/lib/python3.5/site-packages/django/contrib/admin/options.py" in changelist_view
  1655.             selection_note=_('0 of %(cnt)s selected') % {'cnt': len(cl.result_list)},
File "/usr/local/lib/python3.5/site-packages/django/db/models/query.py" in __len__
  144.         self._fetch_all()
File "/usr/local/lib/python3.5/site-packages/django/db/models/query.py" in _fetch_all
  965.             self._result_cache = list(self.iterator())
File "/usr/local/lib/python3.5/site-packages/django/db/models/query.py" in iterator
  238.         results = compiler.execute_sql()
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
  818.             sql, params = self.as_sql()
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in as_sql
  367.             extra_select, order_by, group_by = self.pre_sql_setup()
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in pre_sql_setup
  49.         order_by = self.get_order_by()
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in get_order_by
  276.                     field, self.query.get_meta(), default_order=asc))
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in find_ordering_name
  547.         field, targets, alias, joins, path, opts = self._setup_joins(pieces, opts, alias)
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in _setup_joins
  580.             pieces, opts, alias)
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/query.py" in setup_joins
  1461.             names, opts, allow_many, fail_on_missing=True)
File "/usr/local/lib/python3.5/site-packages/django/db/models/sql/query.py" in names_to_path
  1386.                                      "Choices are: %s" % (name, ", ".join(available)))

Exception Type: FieldError at /admin/django_cron/cronjoblog/
Exception Value: Cannot resolve keyword 'duration' into field. Choices are: code, end_time, id, is_success, message, ran_at_time, start_time

I'm using Django 1.8

Thank you very much

tab-cmd commented 7 years ago

This is clearly a bug, thank you for bringing it to our attention @dorianamouroux . I think we should fix instead of just removing ability to sort @ihoru. This is useful feature when it works!

dorianamouroux commented 7 years ago

I looked a little bit into it, the simplest way would be to create a duration field and store it, otherwise, you can't make it sortable, because the value has to come from the database.

I tried to use queryset.extra() and create the duration value in the SQL query, but depends on the database, the function to calculate the duration is different (DATEDIFF(end_date, start_date) in Mysql, julianday(end_date) - julianday(start_date) in sqlite).

If we create the duration value when we save the model, it wouldn't work for the existing cron log entries, we can create a management command to migrate those.

I can do it and send a PR if you think that's good

tab-cmd commented 7 years ago

@dorianamouroux I think that's a good idea and could be useful elsewhere. Go ahead with it and I'll review the PR. Thanks!