Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-django-rq for
openSUSE:Factory checked in at 2026-04-19 18:17:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-django-rq (Old)
and /work/SRC/openSUSE:Factory/.python-django-rq.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-django-rq"
Sun Apr 19 18:17:05 2026 rev:14 rq:1348052 version:4.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-django-rq/python-django-rq.changes
2026-03-31 16:26:49.018220007 +0200
+++
/work/SRC/openSUSE:Factory/.python-django-rq.new.11940/python-django-rq.changes
2026-04-19 18:17:06.062357453 +0200
@@ -1,0 +2,8 @@
+Sun Apr 19 15:58:24 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 4.1:
+ * Job detail page now shows execution results. Thanks @selwin!
+ * Fixed RQ worker-pool command for projects using Postgres with
+ SSL connections. Thanks @selwin!
+
+-------------------------------------------------------------------
Old:
----
django_rq-4.0.1.tar.gz
New:
----
django_rq-4.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-django-rq.spec ++++++
--- /var/tmp/diff_new_pack.WV3zHP/_old 2026-04-19 18:17:07.446413851 +0200
+++ /var/tmp/diff_new_pack.WV3zHP/_new 2026-04-19 18:17:07.470414829 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-django-rq
-Version: 4.0.1
+Version: 4.1
Release: 0
Summary: Simple app that provides django integration for RQ (Redis
Queue)
License: MIT
++++++ django_rq-4.0.1.tar.gz -> django_rq-4.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/CHANGELOG.md
new/django-rq-4.1/CHANGELOG.md
--- old/django-rq-4.0.1/CHANGELOG.md 2026-03-17 08:44:39.000000000 +0100
+++ new/django-rq-4.1/CHANGELOG.md 2026-04-05 12:32:08.000000000 +0200
@@ -1,3 +1,7 @@
+### Version 4.1 (2026-04-05)
+* Job detail page now shows execution results. Thanks @selwin!
+* Fixed RQ worker-pool command for projects using Postgres with SSL
connections. Thanks @selwin!
+
### Version 4.0.1 (2026-03-17)
* Job detail page now shows a job's dependent jobs. Thanks @selwin!
* Added missing migration that causes Django's makemigrations to complain.
Thanks @bjorndbuilder!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/django_rq/__init__.py
new/django-rq-4.1/django_rq/__init__.py
--- old/django-rq-4.0.1/django_rq/__init__.py 2026-03-17 08:44:39.000000000
+0100
+++ new/django-rq-4.1/django_rq/__init__.py 2026-04-05 12:32:08.000000000
+0200
@@ -1,4 +1,4 @@
-__version__ = "4.0.1"
+__version__ = "4.1.0"
from .connection_utils import get_connection
from .decorators import job
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rq-4.0.1/django_rq/management/commands/rqworker-pool.py
new/django-rq-4.1/django_rq/management/commands/rqworker-pool.py
--- old/django-rq-4.0.1/django_rq/management/commands/rqworker-pool.py
2026-03-17 08:44:39.000000000 +0100
+++ new/django-rq-4.1/django_rq/management/commands/rqworker-pool.py
2026-04-05 12:32:08.000000000 +0200
@@ -8,6 +8,7 @@
from ...jobs import get_job_class
from ...queues import get_queues
+from ...utils import reset_db_connections
from ...workers import get_worker_class
@@ -83,4 +84,6 @@
worker_class=worker_class,
job_class=job_class,
)
+ # Close any opened DB connection before any fork.
+ reset_db_connections()
pool.start(burst=options.get('burst', False),
logging_level=logging_level)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rq-4.0.1/django_rq/templates/django_rq/job_detail.html
new/django-rq-4.1/django_rq/templates/django_rq/job_detail.html
--- old/django-rq-4.0.1/django_rq/templates/django_rq/job_detail.html
2026-03-17 08:44:39.000000000 +0100
+++ new/django-rq-4.1/django_rq/templates/django_rq/job_detail.html
2026-04-05 12:32:08.000000000 +0200
@@ -278,57 +278,42 @@
{% endif %}
</div>
-
- <div class="inline-group" id="choice_set-group">
-
- {% for result in job.results %}
- <h2>Result {{ result.id }}</h2>
- <div class="inline-related">
-
- <fieldset class="module aligned ">
- <div class="form-row field-choice_text">
- <div>
- <div class = "flex-container">
- <label>Type:</label>
- <div class="readonly">
- {{ result.type.name }}
- </div>
- </div>
- </div>
- </div>
-
- <div class="form-row field-votes">
- <div>
- <div class = "flex-container">
- <label>Created at:</label>
- <div class="readonly">{{
result.created_at|to_localtime|date:"Y-m-d, H:i:s" }}</div>
- </div>
- </div>
- </div>
- {% if result.type.value == 1 %}
- <div class="form-row field-votes">
- <div>
- <div class = "flex-container">
- <label>Return value:</label>
- <div><pre>{{ result.return_value }}</pre></div>
- </div>
- </div>
- </div>
- {% elif result.type.value == 2 %}
- <div class="form-row field-votes">
- <div>
- <div class = "flex-container">
- <label>Exception:</label>
- <div><pre>{{ result.exc_string }}</pre></div>
- </div>
- </div>
- </div>
- {% endif %}
-
- </fieldset>
+ {% if job.results %}
+ <div id="job-results">
+ <h3>Results</h3>
+ <div class="results">
+ <table id="result_list">
+ <thead>
+ <tr>
+ <th scope="col" class="sortable">
+ <div class="text"><span>ID</span></div>
+ <div class="clear"></div>
+ </th>
+ <th scope="col" class="sortable">
+ <div class="text"><span>Type</span></div>
+ <div class="clear"></div>
+ </th>
+ <th scope="col" class="sortable">
+ <div class="text"><span>Created At</span></div>
+ <div class="clear"></div>
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for result in job.results %}
+ <tr>
+ <th>
+ <a href="{% rq_url 'result_detail' queue_index
job.id result.id %}">{{ result.id }}</a>
+ </th>
+ <td>{{ result.type.name }}</td>
+ <td>{{ result.created_at|to_localtime|date:"Y-m-d,
H:i:s" }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
</div>
- {% endfor %}
</div>
+ {% endif %}
</div>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/django-rq-4.0.1/django_rq/templates/django_rq/result_detail.html
new/django-rq-4.1/django_rq/templates/django_rq/result_detail.html
--- old/django-rq-4.0.1/django_rq/templates/django_rq/result_detail.html
1970-01-01 01:00:00.000000000 +0100
+++ new/django-rq-4.1/django_rq/templates/django_rq/result_detail.html
2026-04-05 12:32:08.000000000 +0200
@@ -0,0 +1,114 @@
+{% extends "admin/change_list.html" %}
+
+{% load static django_rq %}
+
+{% block title %}Result {{ result.id }} {{ block.super }}{% endblock %}
+
+{% block extrastyle %}
+ {{ block.super }}
+ <style>
+ .data {
+ display: inline-block;
+ float: left;
+ width: 80%;
+ font-size: 12px;
+ padding-top: 3px;
+ }
+ </style>
+ <link href="{% static 'admin/css/forms.css' %}" type="text/css"
rel="stylesheet">
+{% endblock %}
+
+{% block breadcrumbs %}
+ <div class="breadcrumbs">
+ <a href="{% url 'admin:index' %}">Home</a> ›
+ <a href="{% rq_url 'home' %}">Django RQ</a> ›
+ <a href="{% rq_url 'jobs' queue_index %}">{{ queue.name }}</a> ›
+ <a href="{% rq_url 'job_detail' queue_index job.id %}">{{ job.id
}}</a> ›
+ <a href="{% rq_url 'result_detail' queue_index job.id result.id %}">{{
result.id }}</a>
+ </div>
+{% endblock %}
+
+{% block content_title %}<h2>Result {{ result.id }}</h2>{% endblock %}
+
+{% block object-tools %}{% endblock %}
+
+{% block content %}
+
+<div id="content-main">
+
+ <fieldset class="module aligned ">
+
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Job ID:</label>
+ <div class="readonly">
+ <a href="{% rq_url 'job_detail' queue_index job.id
%}">{{ job.id }}</a>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Result ID:</label>
+ <div class="readonly">{{ result.id }}</div>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Type:</label>
+ <div class="readonly">{{ result.type.name }}</div>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Created:</label>
+ <div class="readonly">{{
result.created_at|to_localtime|date:"Y-m-d, H:i:s" }}</div>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Worker:</label>
+ <div class="readonly">{{ result.worker_name|default:"-"
}}</div>
+ </div>
+ </div>
+ </div>
+
+ {% if result.return_value is not None %}
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Return Value:</label>
+ <div><pre>{{ result.return_value }}</pre></div>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+
+ {% if result.exc_string %}
+ <div class="form-row">
+ <div>
+ <div class = "flex-container">
+ <label>Exception:</label>
+ <div><pre>{{ result.exc_string }}</pre></div>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+
+ </fieldset>
+
+</div>
+
+{% endblock %}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/django_rq/urls.py
new/django-rq-4.1/django_rq/urls.py
--- old/django-rq-4.0.1/django_rq/urls.py 2026-03-17 08:44:39.000000000
+0100
+++ new/django-rq-4.1/django_rq/urls.py 2026-04-05 12:32:08.000000000 +0200
@@ -64,6 +64,11 @@
path('queues/<int:queue_index>/requeue-all/',
maybe_wrap(views.requeue_all), name=f'{name_prefix}requeue_all'),
# Job detail and actions
path('queues/<int:queue_index>/<str:job_id>/',
maybe_wrap(views.job_detail), name=f'{name_prefix}job_detail'),
+ path(
+ 'queues/<int:queue_index>/<str:job_id>/results/<str:result_id>/',
+ maybe_wrap(views.result_detail),
+ name=f'{name_prefix}result_detail',
+ ),
path('queues/<int:queue_index>/<str:job_id>/delete/',
maybe_wrap(views.delete_job), name=f'{name_prefix}delete_job'),
path('queues/<int:queue_index>/<str:job_id>/requeue/',
maybe_wrap(views.requeue_job_view), name=f'{name_prefix}requeue_job'),
path('queues/<int:queue_index>/<str:job_id>/enqueue/',
maybe_wrap(views.enqueue_job), name=f'{name_prefix}enqueue_job'),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/django_rq/views.py
new/django-rq-4.1/django_rq/views.py
--- old/django-rq-4.0.1/django_rq/views.py 2026-03-17 08:44:39.000000000
+0100
+++ new/django-rq-4.1/django_rq/views.py 2026-04-05 12:32:08.000000000
+0200
@@ -386,6 +386,30 @@
@never_cache
@staff_member_required
+def result_detail(request: HttpRequest, queue_index: int, job_id: str,
result_id: str) -> HttpResponse:
+ queue = get_queue_by_index(queue_index)
+
+ try:
+ job = Job.fetch(job_id, connection=queue.connection,
serializer=queue.serializer)
+ except NoSuchJobError:
+ raise Http404(f"Couldn't find job with this ID: {job_id}")
+
+ result = next((result for result in job.results() if result.id ==
result_id), None)
+ if not result:
+ raise Http404(f"Couldn't find result with this ID: {result_id}")
+
+ context_data = {
+ **each_context(request),
+ 'queue_index': queue_index,
+ 'job': job,
+ 'queue': queue,
+ 'result': result,
+ }
+ return render(request, 'django_rq/result_detail.html', context_data)
+
+
+@never_cache
+@staff_member_required
def delete_job(request: HttpRequest, queue_index: int, job_id: str) ->
HttpResponse:
queue = get_queue_by_index(queue_index)
job = Job.fetch(job_id, connection=queue.connection,
serializer=queue.serializer)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/integration_test/requirements.txt
new/django-rq-4.1/integration_test/requirements.txt
--- old/django-rq-4.0.1/integration_test/requirements.txt 2026-03-17
08:44:39.000000000 +0100
+++ new/django-rq-4.1/integration_test/requirements.txt 2026-04-05
12:32:08.000000000 +0200
@@ -1,5 +1,5 @@
-e ..
-Django==5.2.11
+Django==5.2.12
gunicorn==23.0.0
psycopg2==2.9.7
-requests==2.32.4
+requests==2.33.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/django-rq-4.0.1/tests/test_views.py
new/django-rq-4.1/tests/test_views.py
--- old/django-rq-4.0.1/tests/test_views.py 2026-03-17 08:44:39.000000000
+0100
+++ new/django-rq-4.1/tests/test_views.py 2026-04-05 12:32:08.000000000
+0200
@@ -5,6 +5,7 @@
from django.test import TestCase, override_settings
from django.test.client import Client
from django.urls import reverse
+from django.utils.html import escape
from rq.job import Job, JobStatus
from rq.registry import (
DeferredJobRegistry,
@@ -68,7 +69,50 @@
url = reverse('admin:django_rq_job_detail', args=[queue_index, job.id])
response = self.client.get(url)
assert result.id
+ self.assertContains(response, 'ID')
+ self.assertContains(response, 'Type')
+ self.assertContains(response, 'Created At')
+ self.assertContains(response, reverse('admin:django_rq_result_detail',
args=[queue_index, job.id, result.id]))
self.assertContains(response, result.id)
+ self.assertContains(response, result.type.name)
+
+ def test_result_details(self):
+ """Result detail page shows successful and failed results and 404s"""
+ queue = get_queue('default')
+ queue_index = get_queue_index('default')
+ worker = get_worker('default')
+
+ job = queue.enqueue(access_self)
+ worker.work(burst=True)
+ result = job.results()[0]
+
+ url = reverse('admin:django_rq_result_detail', args=[queue_index,
job.id, result.id])
+ response = self.client.get(url)
+
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, 'django_rq/result_detail.html')
+ self.assertContains(response, result.id)
+
+ failed_job_instance = queue.enqueue(failing_job)
+ worker.work(burst=True)
+ failed_result = failed_job_instance.results()[0]
+
+ url = reverse('admin:django_rq_result_detail', args=[queue_index,
failed_job_instance.id, failed_result.id])
+ response = self.client.get(url)
+
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(response, failed_result.id)
+ self.assertContains(response, failed_result.type.name)
+ self.assertContains(response, failed_result.worker_name)
+ self.assertContains(response, escape(failed_result.exc_string),
html=True)
+
+ url = reverse('admin:django_rq_result_detail', args=[queue_index,
job.id, 'missing-result-id'])
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 404)
+
+ url = reverse('admin:django_rq_result_detail', args=[queue_index,
'missing-job-id', 'missing-result-id'])
+ response = self.client.get(url)
+ self.assertEqual(response.status_code, 404)
def test_job_details_on_deleted_dependency(self):
"""Page doesn't crash even if job.dependency has been deleted"""
@@ -181,7 +225,9 @@
job_ids.append(job.id)
# remove those jobs using view
- self.client.post(reverse('admin:django_rq_actions',
args=[queue_index]), {'action': 'delete', 'job_ids': job_ids})
+ self.client.post(
+ reverse('admin:django_rq_actions', args=[queue_index]), {'action':
'delete', 'job_ids': job_ids}
+ )
# check if jobs are removed
for job_id in job_ids:
@@ -233,7 +279,9 @@
self.assertTrue(job.is_failed)
# renqueue failed jobs from failed queue
- self.client.post(reverse('admin:django_rq_actions',
args=[queue_index]), {'action': 'requeue', 'job_ids': job_ids})
+ self.client.post(
+ reverse('admin:django_rq_actions', args=[queue_index]), {'action':
'requeue', 'job_ids': job_ids}
+ )
# check if we requeue all failed jobs
for job in jobs: