Version 2 (modified by trac, 3 years ago) ( diff )

--

TicketQuery Wiki Macro

The TicketQuery macro lets you display ticket information anywhere that accepts WikiFormatting. The query language used by the [[TicketQuery]] macro is described in the TracQuery page.

Usage

[[TicketQuery]]

Wiki macro listing tickets that match certain criteria.

This macro accepts a comma-separated list of keyed parameters, in the form "key=value".

If the key is the name of a field, the value must use the syntax of a filter specifier as defined in TracQuery#QueryLanguage. Note that this is not the same as the simplified URL syntax used for query: links starting with a ? character. Commas (,) can be included in field values by escaping them with a backslash (\).

Groups of field constraints to be OR-ed together can be separated by a literal or argument.

In addition to filters, several other named parameters can be used to control how the results are presented. All of them are optional.

The format parameter determines how the list of tickets is presented:

  • list -- the default presentation is to list the ticket ID next to the summary, with each ticket on a separate line.
  • compact -- the tickets are presented as a comma-separated list of ticket IDs.
  • count -- only the count of matching tickets is displayed
  • rawcount -- only the count of matching tickets is displayed, not even with a link to the corresponding query (since 1.1.1)
  • table -- a view similar to the custom query view (but without the controls)
  • progress -- a view similar to the milestone progress bars

The max parameter can be used to limit the number of tickets shown (defaults to 0, i.e. no maximum).

The order parameter sets the field used for ordering tickets (defaults to id).

The desc parameter indicates whether the order of the tickets should be reversed (defaults to false).

The group parameter sets the field used for grouping tickets (defaults to not being set).

The groupdesc parameter indicates whether the natural display order of the groups should be reversed (defaults to false).

The verbose parameter can be set to a true value in order to get the description for the listed tickets. For table format only. deprecated in favor of the rows parameter

The rows parameter can be used to specify which field(s) should be viewed as a row, e.g. rows=description|summary

The col parameter can be used to specify which fields should be viewed as columns. For table format only.

For compatibility with Trac 0.10, if there's a last positional parameter given to the macro, it will be used to specify the format. Also, using "&" as a field separator still works (except for order) but is deprecated.

Examples

Example Result Macro
Number of Triage tickets: 452 [[TicketQuery(status=new&milestone=,count)]]
Number of new tickets: 452 [[TicketQuery(status=new,count)]]
Number of reopened tickets: 0 [[TicketQuery(status=reopened,count)]]
Number of assigned tickets: 607 [[TicketQuery(status=assigned,count)]]
Number of invalid tickets: 5315 [[TicketQuery(status=closed,resolution=invalid,count)]]
Number of worksforme tickets: 1092 [[TicketQuery(status=closed,resolution=worksforme,count)]]
Number of duplicate tickets: 4441 [[TicketQuery(status=closed,resolution=duplicate,count)]]
Number of wontfix tickets: 4268 [[TicketQuery(status=closed,resolution=wontfix,count)]]
Number of fixed tickets: 19310 [[TicketQuery(status=closed,resolution=fixed,count)]]
Number of untriaged tickets (milestone unset): 1059 [[TicketQuery(status!=closed,milestone=,count)]]
Total number of tickets: 36513 [[TicketQuery(count)]]
Number of tickets reported or owned by current user: 1488 [[TicketQuery(reporter=$USER,or,owner=$USER,count)]]
Number of tickets created this month: 58 [[TicketQuery(created=thismonth..,count)]]
Number of closed Firefox tickets: 8 [[TicketQuery(status=closed,keywords~=firefox,count)]]
Number of closed Opera tickets: 26 [[TicketQuery(status=closed,keywords~=opera,count)]]
Number of closed tickets affecting Firefox and Opera: 0 [[TicketQuery(status=closed,keywords~=firefox opera,count)]]
Number of closed tickets affecting Firefox or Opera: 34 [[TicketQuery(status=closed,keywords~=firefox|opera,count)]]
Number of tickets that affect Firefox or are closed and affect Opera: 34 [[TicketQuery(status=closed,keywords~=opera,or,keywords~=firefox,count)]]
Number of closed Firefox tickets that don't affect Opera: 0 [[TicketQuery(status=closed,keywords~=firefox -opera,count)]]
Last 3 modified tickets: #37300, #37299, #31637 [[TicketQuery(max=3,order=modified,desc=1,compact)]]

Details of ticket #1:

[[TicketQuery(id=1,col=id|owner|reporter,rows=summary,table)]]

Ticket Owner Reporter
#1 Jacob Adrian Holovaty
Summary Create architecture for anonymous sessions

Format: list

[[TicketQuery(version=0.6|0.7&resolution=duplicate)]]

This is displayed as:

No results

[[TicketQuery(id=123)]]

This is displayed as:

#123
Typo in the model_api/#field-types

Format: compact

[[TicketQuery(version=0.6|0.7&resolution=duplicate, compact)]]

This is displayed as:

No results

Format: count

[[TicketQuery(version=0.6|0.7&resolution=duplicate, count)]]

This is displayed as:

0

Format: progress

[[TicketQuery(milestone=0.12.8&group=type,format=progress)]]

This is displayed as:

Uncategorized

2048 / 2049

Bug

10679 / 11032

New feature

3897 / 4287

Cleanup/optimization

5616 / 5930

Format: table

You can choose the columns displayed in the table format (format=table) using col=<field>. You can specify multiple fields and the order they are displayed in by placing pipes (|) between the columns:

[[TicketQuery(max=3,status=closed,order=id,desc=1,format=table,col=resolution|summary|owner|reporter)]]

This is displayed as:

Full rows

In table format you can specify full rows using rows=<field>:

[[TicketQuery(max=3,status=closed,order=id,desc=1,format=table,col=resolution|summary|owner|reporter,rows=description)]]

This is displayed as:

Results (1 - 3 of 35454)

1 2 3 4 5 6 7 8 9 10 11
Ticket Resolution Summary Owner Reporter
#37288 needsnewfeatureprocess Add first-class rate limiting support for Django views Bader Eddine Benhirt
Description

Django currently doesn't provide a built-in general-purpose mechanism for rate limiting HTTP views.

Applications that need to protect endpoints against excessive requests currently rely on third-party packages, custom middleware, reverse proxies, or framework-specific solutions such as Django REST Framework throttling.

I propose adding a small, framework-level rate limiting abstraction to Django that can be used by regular function-based and class-based views.

A possible API could look like:

@rate_limit("api")
def index(request):
    ...


@rate_limit("api", methods={"POST", "PUT"})
def edit(request):
    ...


@rate_limit("exports", tokens=5)
def export(request):
    ...

Rate limit policies could be defined centrally in settings:

RATE_LIMITS = {
    "api": {
        "rate": "100/m",
        "key": "ip",
    },
    "exports": {
        "rate": "10/h",
        "key": "user",
    },
}

When a request exceeds its configured limit, Django could return an HTTP 429 Too Many Requests response and optionally include a Retry-After header.

The implementation should ideally support:

function-based views and class-based views.

  • authenticated-user and IP-based keys.
  • custom callable keys.
  • HTTP-method-specific limits.
  • multiple rate limits on the same view.
  • configurable request/token cost.
  • Django's cache abstraction as a storage backend.
  • synchronous and asynchronous views.
  • 429 Too Many Requests and Retry-After.
  • safe and clearly documented concurrency semantics.

There is already ticket #21289 concerning login rate limiting in contrib.auth, but this proposal would provide a more general primitive for Django HTTP views rather than being specific to authentication.

Similar declarative approaches now exist in other frameworks. For example, Symfony 8.1 introduced a controller-level #[RateLimit] attribute. This proposal would not aim to reproduce Symfony's API, but rather explore a Django-native equivalent.

An important design question is whether this belongs in Django core or should remain a third-party package. If considered suitable for core, I would be interested in working on the implementation.

#37287 duplicate Add Index on LogEntry.action_time to optimize admin dashboard performance Ali Rafiei Ali Rafiei
Description

Problem & Motivation

In high-traffic production environments, the django_admin_log table often grows to millions of rows. Every time a user loads the main Django Admin Index (dashboard) page, the framework displays the "Recent actions" sidebar. This forces the following query to execute: 

SELECT ... FROM "django_admin_log" ORDER BY "django_admin_log"."action_time" DESC LIMIT 10;

Because LogEntry explicitly defines ordering = -action_time in its Meta options but lacks any indexing on the action_time field, database engines must perform a highly inefficient sequential table scan to retrieve these 10 rows. This causes severe CPU spikes and long page-load delays on large datasets, as highlighted in recent community discussions (e.g., Django Forum thread https://forum.djangoproject.com/t/strange-behaviour-for-django-5-0-long-loading-times-and-high-postgres-cpu-load-only-admin/41943). 

Historical Context & Precedent

The structural performance limitations of django_admin_log are well-documented. Similar bottlenecks regarding missing indexes were flagged in Ticket #17659 and Ticket #36414

While previous community efforts to index django_admin_log faced roadblocks—specifically regarding the object_id column because MySQL struggles to index unbounded text columns—action_time is a standard DateTimeField. Adding an index here carries no cross-database compatibility issues and is universally supported across PostgreSQL, MySQL, SQLite, and Oracle. 

Proposed Solution To address this bottleneck, I propose adding an explicit descending index on action_time directly to LogEntry.Meta.indexes (e.g., models.Index(fields=-action_time and generate the corresponding core migration for contrib.admin. This targets an un-bypassable query built into Django's default UI and guarantees predictable performance scaling for enterprise installations.

#37285 duplicate `manage.py check` started requiring DB to exist (PostgreSQL) Ran Benita
Description

Hi,

I just attempted 6.0 -> 6.1 upgrade, and found that ./manage.py check started requiring the DB to exist. I am using PostgreSQL, and the traceback suggests this may be PG-backend-specific due to the new PG supports_virtual_generated_columns feature in 6.1. It checks the PG version which I guess needs an active DB connection.

This is a problem for me because I run ./manage.py check in CI without the DB present. I think it makes sense because I run it in the "lint" phase of my CI checks, and there has not previously been a reason to have the DB exist in CI (note this is the e.g. mydb defined in DATABASES, not test_mydb).

If this is intended behavior that check requires a DB to be present, and my use just happened to work before, it's easy enough to workaround, but I thought perhaps it might not be intended.

Traceback:

$ ./manage.py check
Traceback (most recent call last):
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 279, in ensure_connection
    self.connect()
    ~~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 256, in connect
    self.connection = self.get_new_connection(conn_params)
                      ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/postgresql/base.py", line 345, in get_new_connection
    connection = self.Database.connect(**conn_params)
  File "snipped/.venv/lib/python3.14/site-packages/psycopg/connection.py", line 122, in connect
    raise last_ex.with_traceback(None)
psycopg.OperationalError: connection failed: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "mydb" does not exist

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "snipped/manage.py", line 5, in <module>
    main()
    ~~~~^^
  File "snipped/manage.py", line 73, in main
    execute_from_command_line(sys.argv)
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
    ~~~~~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/__init__.py", line 437, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/base.py", line 422, in run_from_argv
    self.execute(*args, **cmd_options)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/base.py", line 466, in execute
    output = self.handle(*args, **options)
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/commands/check.py", line 81, in handle
    self.check(
    ~~~~~~~~~~^
        app_configs=app_configs,
        ^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
        databases=options["databases"],
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "snipped/.venv/lib/python3.14/site-packages/django/core/management/base.py", line 498, in check
    all_issues = checks.run_checks(
        app_configs=app_configs,
    ...<2 lines>...
        databases=databases,
    )
  File "snipped/.venv/lib/python3.14/site-packages/django/core/checks/registry.py", line 99, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "snipped/.venv/lib/python3.14/site-packages/django/core/checks/model_checks.py", line 36, in check_all_models
    errors.extend(model.check(**kwargs))
                  ~~~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 1785, in check
    *cls._check_fields(**kwargs),
     ~~~~~~~~~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/models/base.py", line 1948, in _check_fields
    errors.extend(field.check(**kwargs))
                  ~~~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/models/fields/generated.py", line 84, in check
    *self._check_supported(databases),
     ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/models/fields/generated.py", line 135, in _check_supported
    connection.features.supports_virtual_generated_columns
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/postgresql/features.py", line 186, in is_postgresql_18
    return self.connection.pg_version >= 180000
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/functional.py", line 47, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
                                         ~~~~~~~~~^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/postgresql/base.py", line 556, in pg_version
    with self.temporary_connection():
         ~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File ".local/share/uv/python/cpython-3.14.6-linux-x86_64-gnu/lib/python3.14/contextlib.py", line 141, in __enter__
    return next(self.gen)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 695, in temporary_connection
    with self.cursor() as cursor:
         ~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 320, in cursor
    return self._cursor()
           ~~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 296, in _cursor
    self.ensure_connection()
    ~~~~~~~~~~~~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 278, in ensure_connection
    with self.wrap_database_errors:
         ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/db/utils.py", line 94, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 279, in ensure_connection
    self.connect()
    ~~~~~~~~~~~~^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/base/base.py", line 256, in connect
    self.connection = self.get_new_connection(conn_params)
                      ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "snipped/.venv/lib/python3.14/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "snipped/.venv/lib/python3.14/site-packages/django/db/backends/postgresql/base.py", line 345, in get_new_connection
    connection = self.Database.connect(**conn_params)
  File "snipped/.venv/lib/python3.14/site-packages/psycopg/connection.py", line 122, in connect
    raise last_ex.with_traceback(None)
django.db.utils.OperationalError: connection failed: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  database "mydb" does not exist
1 2 3 4 5 6 7 8 9 10 11


See also: TracQuery, TracTickets, TracReports

Note: See TracWiki for help on using the wiki.
Back to Top