django-data-browser
Interactive, user-friendly database explorer.
::: {.contents depth="1"} :::
Demo
There is a live demo site available here https://data-browser-demo.herokuapp.com/data-browser/.
Because it\'s hosted on Heroku free tier it might take a while to respond to the first page load.
The Django project is a small e-commerce site selling microservices.
Source: https://github.com/tolomea/data-browser-demo.
Admin: https://data-browser-demo.herokuapp.com/admin/.
Features
- Zero config, if it\'s in the admin it\'s in the browser.
- Select fields (including calculated fields), aggregate, filter, sort and pivot.
- Automatically follow OneToOneFields and ForeignKeys.
- Respects per user admin permissions.
- Share views simply by sharing URLs.
- Save views and optionally make them available to services like Google sheets.
- Download views as CSV or JSON.
Supported Versions
The Data Browser is currently tested on:
- Django 3.2 - 5.0
- Python 3.8 - 3.12
- MySQL, PostgreSQL, SQLite
We highly recommend and only officially support the latest patch release of each Python and Django series.
Installation
- Run
pip install django-data-browser
. - Add
"data_browser"
to installed_apps. - Add
path("data-browser/", include("data_browser.urls"))
to your urls. - Run
python manage.py migrate
. - If you have queryset annotations in your admin or are interested in exposing calculated values see the Calculated and Annotated fields section.
Settings
+-------------+-----+-----------+-------------------------------------+
| Name | D | Docs | Function |
| | efa | Section | |
| | ult | | |
+=============+=====+===========+=====================================+
| DATA_BRO |
| | Set the name for the \"open in |
| WSER_ADMIN_ | adm | | Django admin\" field. |
| FIELD_NAME| in
| | |
+-------------+-----+-----------+-------------------------------------+
| DATA |
| Se | Allow selected saved views to be |
| _BROWSER_AL | Fal | curity | limited circumstances. |
+-------------+-----+-----------+-------------------------------------+
| DATA_BRO |
Tr | [Performa | When calling get_fieldsets
on a |
| WSER_AUTH_U | ue| nce](#per |
UserAdminalways pass an instance |
| SER_COMPAT
| | formance) | of the associated model. |
+-------------+-----+-----------+-------------------------------------+
| DATA_BROW |
10 | | The default value for the row limit |
| SER_DEFAULT | 00| | selector in the UI. |
| _ROW_LIMIT
| | | |
+-------------+-----+-----------+-------------------------------------+
| DATA_B |
| CONTRIB | Enable proxying frontend to JS dev |
| ROWSER_DEV| Fal | UTING.rst | server. |
| | se
| | |
+-------------+-----+-----------+-------------------------------------+
| DATA_BROW |
No | [Sentry] | The DSN the frontend sentry should |
| SER_FE_DSN| ne
| (#sentry) | report to, disabled by default. |
+-------------+-----+-----------+-------------------------------------+
| |
" | [Performa | Specify a database alias to use by |
| DATA_BROWSE | def | nce](#per | default on all database queries. |
| R_USING_DB| aul | formance) | |
| | t"
| | |
+-------------+-----+-----------+-------------------------------------+
| DATA_ |
| S | Set admin specific configuration |
| BROWSER_ADM | {}| pecifying | options. |
| IN_OPTIONS
| | models | |
| | | and | |
| | | fi | |
| | | elds | |
+-------------+-----+-----------+-------------------------------------+
| DATA_ |
Tr | | Are the app sections of the |
| BROWSER_APP | ue| | homepage model list expanded by |
| S_EXPANDED
| | | default. |
+-------------+-----+-----------+-------------------------------------+
| DA |
No | > Admin | Specify an admin.AdminSite
to use |
| TA_BROWSER_ | ne| > | (default is
admin.site). |
| ADMIN_SITE
| | Site | |
+-------------+-----+-----------+-------------------------------------+
Permissions
data_browser.make_view_public
Security Can make a saved view publicly
available.
data_browser.share_view
Can share a saved view with
other users.
Security
Most of the Django views in the Data Browser can only be accessed by Django \"staff members\". These views support general querying of the database, checked against the admin permissions of the logged in user.
The only exception to this is \"Public Saved Views\" these are views which have been saved and marked as public. They can be accessed by anyone without needing a login but they can only be used to access a query that has been saved and made public and they have long random URL\'s.
You can use the admin permission
data_browser | view | Can make a saved view publically available
to
restrict who can make views public. To be public the view must be marked
as public and owned by someone who has the permission.
Additionally the entire public views system is gated by the Django
settings value DATA_BROWSER_ALLOW_PUBLIC
.
Sentry
The frontend code has builtin Sentry support, it is disabled by
default. To enable it set the Django settings value
DATA_BROWSER_FE_DSN
, for example to set it to the Data Browser project
Sentry use:
DATA_BROWSER_FE_DSN = "https://[email protected]/5231151"
Linking to the Data Browser
The home page URL of the Data Browser is given by
reverse("data_browser:home")
.
Additionally if you are using data_browser.helpers.AdminMixin
then in
Admin list views the URL of the Data Browser page for the same model is
available as the template context variable ddb_url
.
One convenient way of utilizing this is to create the file
templates/admin/change_list_object_tools.html
and populate it with:
{% extends "admin/change_list_object_tools.html" %}
{% block object-tools-items %}
{{ block.super }}
{% if ddb_url %}
<li><a href="{{ ddb_url }}" class="viewlink">Data Browser</a></li>
{% endif %}
{% endblock %}
This will place a \"Data Browser\" button on the list view of every admin that inherits from the mixin. Note: to do this at the top level, the app you put the template in must be before contrib.admin in INSTALLED_APPS.
Specifying models and fields
By default the Data Browser has access to all models and fields that the
current user can see anywhere in the Admin site. However if necessary
this can be tweaked using the following class level properties and
functions on ModelAdmin
s and Inline
s.
+-------------+---------------+----------------------------------------+
| > Name | Format | Purpose |
+=============+===============+========================================+
| | |
bool| Ignore this Admin / Inline entirely, |
| ddb_ignore
| | will still show fields from other |
| | ge | | Inlines / Admins on the same model. |
| t_ddb_ignor | | |
| e(request)
| | |
+-------------+---------------+----------------------------------------+
| | ddb_h |
| Explicitly hide the specified fields. |
| ide_fields| [field_name]
| |
| | get_ddb | | |
| _hide_field | | |
| s(request)
| | |
+-------------+---------------+----------------------------------------+
| | ddb_ex |
| Add additional fields that are not |
| tra_fields| [field_name]
| mentioned in fields, fieldsets or |
| | get_ddb_ | | list_display. |
| extra_field | | |
| s(request)
| | |
+-------------+---------------+----------------------------------------+
| | ddb_j |
{field_name: | Expose fields within JSON data for |
| son_fields| {json_field_ | access in the Data Browser. Type can |
| |
get_ddb | name: type}}| be \"string\", \"number\" or |
| _json_field | | \"boolean\". |
| s(request)
| | |
+-------------+---------------+----------------------------------------+
| | | [(path, loo | | Default filters to be added when |
|
ddb_defau | kup, value)]| opening this model. |
| lt_filters
| | | E.G. to add |
| | get_ | |
client__name__equals=Testuse |
| ddb_default | |
|
| _filters()| | [("client__name", "equals", "Test")]
. |
+-------------+---------------+----------------------------------------+
| | ddb_ |
str| The url to post admin actions to, |
| action_url
| | usually the changelist view. See |
| | get_dd | | [Admin Actions](#admin-actions) |
| b_action_ur | | |
| l(request)
| | |
+-------------+---------------+----------------------------------------+
These can also be set via the settings entry
DATA_BROWSER_ADMIN_OPTIONS
, this is useful if you wish to change an
option on a third party admin. The format for this is
{'my_package.MyAdmin': {'option': value}}
, for example to remove
Django Q\'s Task and Fail admins entirely you would use:
DATA_BROWSER_ADMIN_OPTIONS = {
'django_q.admin.TaskAdmin': {'ignore': True},
'django_q.admin.FailAdmin': {'ignore': True},
}
Finally, per the below sections, calculated fields and actions can be
hidden by setting the ddb_hide
attribute and annotated fields are
always visible unless explicitly hidden.
Calculated and Annotated fields
Calculated
Calculated fields are fields on the ModelAdmin
whose value comes from
a function on the ModelAdmin
or a function or property on the Model
itself, as described at the bottom of the Django admin list display
docs.
Being arbitrary Python code calculated fields are opaque to the Data Browser. It can fetch their values but can\'t sort or filter etc on them. For pivoting they are treated as equivalent to the pk on the same model.
Additionally calculated fields can be hidden from the Data Browser by
setting the attribute ddb_hide
to True
. The
data_browser.helpers.attributes
decorator can make this a little
tidier.
@attributes(ddb_hide=True)
def my_calculated_field(self, obj):
return ...
Annotated
The Data Browser has additional support for annotated fields. Normally
you would expose these as calculated fields. The module
data_browser.helpers
contains helpers which will make exposing
annotated fields simpler, more performant and expose them to the Data
Browser so it can do arbitrary manipulation with them.
Exposing an annotated field in this way requires two changes.
- Mix
data_browser.helpers.AdminMixin
into your ModelAdmin. - Add a function decorated with
data_browser.helpers.annotation
that takes and updates a queryset.
from data_browser.helpers import AdminMixin, annotation
@admin.register(MyModel)
class MyAdmin(AdminMixin, ModelAdmin):
fields = ["my_field"]
@annotation
def my_field(self, request, qs):
return qs.annotate(my_field=Cast(..., output_field=IntegerField()))
WARNING: annotated aggregations will produce misleading results when further aggregated in the Data Browser.
It is important that the decorated annotation function name and the annotated queryset field name match.
Sometimes it is necessary for the top level of the annotation to have
output_field
set so the Data Browser can tell what type of data it
will produce. When this is necessary you will get an error to that
effect.
The helpers will automatically deal with the admin_order_field
and
boolean
properties and readonly_fields
, reducing the boiler plate
involved in using annotations in the admin.
Additionally the annotation will only be applied to the list view when
it\'s mentioned in list_display
this allows you to use annotations
extensively on your detail views without hurting the performance of your
list views.
And finally even if not mentioned in fields, fieldsets or list_display,
the annotation will still be visible in the Data Browser unless it is
explicitly mentioned in ddb_hide_fields
.
Performance
get_queryset()
The Data Browser does it\'s fetching in two stages.
First it does a single DB query to get the majority of the data. To
construct the queryset for this it will call get_queryset()
on the
ModelAdmin
of the current Model. It uses .values()
to fetch only the
data it needs from the database and it will inline all referenced models
to ensure it doesn\'t do multiple queries.
At this stage annotated fields on related models are attached with
subquery annotations, the data browser will call get_queryset()
on the
relevant ModelAdmin
s in order to generate these subquery annotations.
Secondly for any calculated fields it will then fetch the complete
objects that are needed for those calculated fields. To construct the
querysets for these it will call get_queryset()
on their associated
ModelAdmin
s. These calls are aggregated so it will only make one per
model.
As a simple example, if you did a query against the Book
model for the
fields:
book.name
book.author.name
book.author.age
book.author.number_of_books
book.publisher.name
Where the author.age
is actually a property on the Author
model, and
author.number_of_books
is an @annotation
on the Author
ModelAdmin
, then it would do something like the following two queries:
BookAdmin.get_queryset().annotate(
author__number_of_books=Subquery(
AuthorAdmin.get_queryset()
.filter(pk=OuterRef("author__id"))
.values("number_of_books")[:1]
)
).values(
"name",
"author__name",
"author__id",
"author__number_of_books",
"publisher__name",
)
AuthorAdmin.get_queryset().in_bulk(pks=...)
Where the pks
passed to in_bulk in the second query came from
author__id
in the first.
You can view an approximation of the main queryset by changing the [.html]{.title-ref} in the URL to [.qs]{.title-ref}. In a similar manner [.sql]{.title-ref}, [.explain]{.title-ref} and [.analyze]{.title-ref} are also available.
When the Data Browser calls the admin get_queryset()
functions it will
put some context in request.data_browser
. This allows you to test to
see if the Data Browser is making the call as follows:
if hasattr(request, "data_browser"):
# Data Browser specific customization
This is particularly useful if you want to route the Data Browser to a DB replica for a particular model (n.b. if you want to do this for all models see QuerySet.using() below.).
The context also includes a fields
member that lists all the fields
the Data Browser plans to access. You can use this to do conditional
prefetching or annotating to support those fields like this:
if (
not hasattr(request, "data_browser")
or "my_field" in request.data_browser["fields"]
):
# do prefetching and annotating associated with my_field
The AdminMixin described in the Calculated and Annotated
fields section is doing this
internally for @annotation
fields.
QuerySet.using()
The setting DATA_BROWSER_USING_DB
can be used to direct Data Browser
initiated database queries to a replica. Underneath the value of this is
passed into QuerySet.using()
.
ModelAdmin.get_fieldsets()
The Data Browser also calls get_fieldsets
to find out what fields the
current user can access.
As with get_queryset
the Data Browser will set request.data_browser
when calling get_fieldsets
and you can test this to detect it and make
Data Browser specific customizations.
The Django User Admin has code to change the fieldsets when adding a new
user. To compensate for this, when calling get_fieldsets
on a subclass
of django.contrib.auth.admin.UserAdmin
the Data Browser will pass a
newly constructed instance of the relevant model. This behavior can be
disabled by setting settings.DATA_BROWSER_AUTH_USER_COMPAT
to False
.
Admin Actions
Django\'s Admin actions are exposed by right clicking on ID (or other appropriate pk field) column headers.
Due to the way these are implemented in Django there are some additional technical considerations.
The actions are posted to the Admin changelist URL. Once this post
happens the Data Browser is no longer involved and so can\'t set
request.data_browser
like it normally would. Instead it will set the
post argument data_browser
.
When the Data Browser triggers actions default Admin filtering is
applied. If you have Admin filters that hide rows by default then
actions triggered from the Data Browser will not be able to access those
rows. To work around this you can specify get_ddb_action_url
to
override the URL the actions are posted to. By default it returns the
changelist URL so you can append any arguments needed to set filters to
not filter.
Style customization
You can override the data_browser/index.html
template per Django's
template overriding
docs,
and replace the extrahead
block. (Ensure "data_browser"
is after
your app in INSTALLED_APPS
.)
This will let you inject custom CSS and stylesheets.
However note that because of how the normal CSS is injected any custom
CSS will be before the normal CSS so you will need to use more specific
selectors or !important
.
Custom functions and aggregations
It is possible to register additional functions and aggregations with the Data Browser, including custom ones.
Types
Functions and Aggregations are attached to the Data Browsers core types,
these are in data_browser.types
.
Functions
This functionality is provisional and not subject to normal backward compatible guarantees.
The function registry is in data_browser.orm_functions.TYPE_FUNCTIONS
this has type
dict[BaseType, dict[str, data_browser.orm_functions.Func]]
. It is safe
to insert new entries into this at runtime.
For example to add the MD5 function to string fields you could do the following:
from django.db.models.functions import MD5
from data_browser.types import StringType
from data_browser.orm_functions import Func, TYPE_FUNCTIONS
TYPE_FUNCTIONS[StringType]["md5"] = Func(MD5, StringType)
Aggregates
This functionality is provisional and not subject to normal backward compatible guarantees.
The aggregate registry is in
data_browser.orm_aggregates.TYPE_AGGREGATES
this has type
dict[BaseType, dict[str, data_browser.orm_aggregates.Agg]]
. It is safe
to insert new entries into this at runtime.
For example to add a count that does not apply distinct to number fields you could do the following:
from django.db.models import Count
from data_browser.types import NumberType
from data_browser.orm_aggregates import Agg, TYPE_AGGREGATES
TYPE_AGGREGATES[NumberType]["full_count"] = Agg(
lambda x: Count(x, distinct=False), NumberType
)
Custom SQL example
For a larger example imagine you wanted to use Postgres\'s
percentile_cont
functionality to add a p95
aggregate to duration
fields, perhaps for some kind of application performance monitoring
usecase.
First we need to explain percentile_cont
to Django.
from django.db.models import Aggregate
class Percentile(Aggregate):
arity = 1
function = "percentile_cont"
template = "%(function)s(%(percentile)s) WITHIN GROUP (ORDER BY %(expressions)s)"
name = "Percentile"
def __init__(self, percentile, expressions, **extra):
super().__init__(expressions, percentile=percentile, **extra)
Then we need to tell the Data Browser we want p95
on duration fields.
from data_browser.orm_aggregates import TYPE_AGGREGATES, Agg
from data_browser.types import DurationType
TYPE_AGGREGATES[DurationType]["p95"] = Agg(
lambda x: Percentile(0.95, x), DurationType
)
Admin Site
You can create and use a custom admin.AdminSite
(see
https://docs.djangoproject.com/en/4.2/ref/contrib/admin/).
To do so, in your settings.py
, add:
from django.contrib import admin
class BrowserAdminSite(admin.AdminSite):
pass
DATA_BROWSER_ADMIN_SITE = BrowserAdminSite(name='data_browser')
Then, in any admin.py
, register the models as usually but using
DATA_BROWSER_ADMIN_SITE
.
For instance in myapp/admin.py
:
from django.contrib import admin
from django.conf import settings
from myapp.models import MyAdminModel, MyBrowsableModel
# register in admin only
admin.register(MyAdminModel)
# register in data browser only
settings.DATA_BROWSER_ADMIN_SITE.register(MyBrowsableModel)
Version numbers
The Data Browser uses the standard Major.Minor.Patch
version numbering
scheme.
Patch versions may include bug fixes and minor features.
Minor versions are for significant new features.
Major versions are for major features, significant changes to existing functionality and breaking changes.
Patch and Minor versions should never contain breaking changes and should always be backward compatible. A breaking change is a change that makes backward incompatible changes to one or more of the following:
- The query URL format.
- The json, csv etc data formats, this does not include the Data Browsers internal API\'s, only the data export formats.
- The format of the
request.data_browser
passed toget_fieldsets
andget_queryset
. - Existing saved views.
- The URL\'s of public saved views.
For alpha and beta releases absolutely anything may change / break.
Release History
+----+------+---------------------------------------------------------+
| V | Date | Summary |
| er | | |
| si | | |
| on | | |
+====+======+=========================================================+
| 4. | 20 | | Fix Z fighting issue with the field filter. |
| 2. | 24-0 | | Refactor JS for greater speed. |
| 10 | 4-08 | | Fix a regex escaping issue in the field filter. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Make field filter matching more permissive. |
| .2 | 24-0 | | Add a distinct (cyan) color for annotated fields. |
| .9 | 4-02 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Improve field filter matching. |
| .2 | 24-0 | | Add sticky headers to the field list. |
| .8 | 2-11 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | Add a text filter to the top of the field list. |
| .2 | 24-0 | |
| .7 | 2-04 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Support custom admin sites. Contributed by |
| .2 | 24-0 | #aboutofpluto |
| .6 | 2-04 | | Fix date expression in a filter on a datetime field |
| | | not anchoring to midnight. |
| | | | Use verbose names for apps and models. |
| | | | Add support for Python 3.12 and Django 5.0, drop |
| | | support for Python 3.7. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Fix parsing of date/datetime strings like mon-1
. |
| .2 | 23-0 | | Add support for DB query analyze via .analyze
url, |
| .5 | 7-20 | similar to the existing .explain
. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Provisional support for adding custom functions and |
| .2 | 23-0 | aggregations. |
| .4 | 7-02 | | Fix all
aggregate on booleans and durations. |
| | | (Postgres only) |
+----+------+---------------------------------------------------------+
| 4 | 20 | Fix ASGI compatibility issue. |
| .2 | 23-0 | |
| .3 | 6-15 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | Fix various issues around saved view validity. |
| .2 | 23-0 | |
| .2 | 6-08 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | BREAKING: In JSON format move parsed
and |
| .2 | 23-0 | fitlerErrors
onto the filters. |
| .1 | 5-21 | | Display invalid fields (previously they were |
| | | ignored). |
| | | | Fix small bug when removing filters with errors. |
+----+------+---------------------------------------------------------+
| 4 | 20 | Fix bug with shared views when using multiple |
| .1 | 23-0 | authentication backends. |
| .1 | 5-07 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Support sharing of saved views between users. |
| .1 | 23-0 | | Allow mixing of folders and views in the saved views |
| .0 | 5-01 | section. |
| | | | Fix bug where an invalid filter causes the query page |
| | | to fail to render. |
+----+------+---------------------------------------------------------+
| 4. | 20 | Fix bug with admin actions only working on the first |
| 0. | 23-0 | column (introduced in 4.0.14). |
| 17 | 4-25 | |
+----+------+---------------------------------------------------------+
| 4. | 20 | | Group homepage model list into collapsible sections |
| 0. | 23-0 | by app. |
| 16 | 4-16 | | Allow grouping saved views into collapsible folders. |
+----+------+---------------------------------------------------------+
| 4. | 20 | | Clear confirm prompts after a short delay. |
| 0. | 23-0 | | Remember the current saved view and allow updating |
| 15 | 4-11 | it. |
+----+------+---------------------------------------------------------+
| 4. | 20 | | Fix bug with admin actions not respecting ordering |
| 0. | 23-0 | when the number of results exceeds the limit. |
| 14 | 4-05 | | Add support for Django 4.2 and Python 3.11 drop |
| | | support for Django 2.2, 3.0 and 3.1. |
| | | | Make \"to many\" support generally available. |
+----+------+---------------------------------------------------------+
| 4. | 20 | | Add support for Django 4.1. |
| 0. | 23-0 | | Work with CSRF_COOKIE_HTTPONLY which is enabled by |
| 13 | 3-06 | cookiecutter-django. |
+----+------+---------------------------------------------------------+
| 4. | 20 | Allow setting the per admin options via |
| 0. | 22-0 | DATA_BROWSER_ADMIN_OPTIONS
. |
| 12 | 5-03 | |
+----+------+---------------------------------------------------------+
| 4. | 20 | Fix bug when DATA_BROWSER_ADMIN_FIELD_NAME
contains |
| 0. | 22-0 | spaces. |
| 11 | 4-12 | |
+----+------+---------------------------------------------------------+
| 4. | 20 | | Make results stable by always sorting all fields. |
| 0. | 22-0 | | Fix an issue with few to no results when pivoted and |
| 10 | 4-10 | the headers exceed the result limit. |
| | | | Add support for Postgres\'s array length function. |
| | | | Allow overriding the \"open in Django admin\" field |
| | | name with DATA_BROWSER_ADMIN_FIELD_NAME
. |
| | | | Add an AppConfig and declare the |
| | | default_auto_field
. |
| | | | Expose access to QuerySet.using()
via a new |
| | | DATA_BROWSER_USING_DB
setting. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Fix contains filter not working on files and URLs. |
| .0 | 22-0 | | Allow combining literal date time values with |
| .9 | 1-04 | relative clauses. |
| | | | Expose Postgres\'s ArrayAgg
as an all
aggregate. |
| | | | Add mouse over text for the \"to many\" icon. |
| | | | Fix issue when related_name
is different from |
| | | related_query_name
|
| | | | CSS tweaks. |
| | | | Change calculated field red to grey. |
| | | | Add support for Django 4.0 and Python 3.10 drop |
| | | support for Python 3.6. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Fix formatting of F
expressions when using .qs
. |
| .0 | 21-1 | | Make the field list and filter list collapsible. |
| .8 | 2-12 | | CSS tweaks. |
| | | | Add public view info to request.data_browser
. |
| | | | Fix crash when length filtering arrays of choice |
| | | fields. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Add support for django-hashid-field. |
| .0 | 21-0 | | Fix a crash bug when aggregating fields with names |
| .7 | 8-16 | starting with _
. |
+----+------+---------------------------------------------------------+
| 4 | 20 | Fix spelling mistake. |
| .0 | 21-0 | |
| .6 | 8-10 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Don\'t override right click context menu for HTML |
| .0 | 21-0 | values (e.g. \"Admin\" columns). |
| .5 | 8-09 | | Fix \"bad lookup\" when excluding IsNull
/NotNull
|
| | | values. |
| | | | Fix pressing enter clearing all filters. |
| | | | Fix exceptions when using .qs
. |
| | | | Fix view link on Saved View admin page not preserving |
| | | limit
. |
| | | | Improve placement of context menus. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | Add .qs
format support to see the main Django |
| .0 | 21-0 | Queryset. |
| .4 | 7-04 | | Support weeks
in date and datetime filters. |
| | | | Fix bug filtering functions on annotations e.g. |
| | | __my_annotation__is_null=IsNull
. |
| | | | Add admin actions to the admin column in addition to |
| | | the id column. |
| | | | Add exclude option to right click menus. |
+----+------+---------------------------------------------------------+
| 4 | 20 | Test on Django 3.2. |
| .0 | 21-0 | |
| .3 | 6-18 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | URL, image and file fields filter like strings and |
| .0 | 21-0 | render as strings in CSV and JSON. |
| .2 | 4-12 | |
+----+------+---------------------------------------------------------+
| 4 | 20 | | URLFields display as links. |
| .0 | 21-0 | | Change pivot icon. |
| .1 | 4-11 | | Automatically include the other side of OneToOne |
| | | fields. |
| | | | Disable custom context menus when right clicking |
| | | inside a text selection. |
| | | | Fix rare issue with helpers.AdminMixin and MRO |
| | | ordering of child classes. |
+----+------+---------------------------------------------------------+
| 4 | 20 | | In the JSON output aggregate fields are now always in |
| .0 | 21-0 | the body. |
| .0 | 3-13 | | The CSV format has changed so aggregate fields are |
| | | always to the right of other fields. |
| | | | In the UI aggregate fields are now always to the |
| | | right of other fields. |
| | | | Fields are colored by type, green: normal, blue: |
| | | aggregates, red: can\'t sort or filter. |
| | | | The right click drill down action now only adds |
| | | filters where the row/column has multiple values. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Drop support for Django 2.0 and 2.1 |
| .3 | 21-0 | | Rework Admin action integration. |
| .0 | 2-19 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Date filter values formated as 2020-1-2
are now |
| .2 | 21-0 | considered ISO ordered and no longer ambiguous. |
| .5 | 2-07 | | Rework \@annotation and AdminMixin so \@annotation |
| | | can be used on mixins. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Fix equals
and not equals
not working for array |
| .2 | 21-0 | fields. |
| .4 | 2-02 | | Improve date and datetime filter errors. |
| | | | Improve and contrast display of null and empty |
| | | string. |
| | | | Various fixes for models where the primary key is not |
| | | id
. |
| | | | Empty but non null file fields render as empty string |
| | | instead of null. |
| | | | Fix is null
not working with the year
function. |
| | | | The field list is now sorted by display name (except |
| | | for the primary key and admin link). |
| | | | Fix not equals
excluding nulls with functions and |
| | | aggregates, e.g. year
, min
etc. |
| | | | Right click filter and drill down now correctly |
| | | handle null values. |
| | | | Prevent exception when a saved views name gets too |
| | | long. |
+----+------+---------------------------------------------------------+
| 3 | 20 | Fix issue when using a filter with a different type |
| .2 | 21-0 | from the field, e.g. is null
. |
| .3 | 1-11 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Fix id
field missing from some models. |
| .2 | 20-1 | | Per Django, Django 2.0 & 2.1 are not supported on |
| .2 | 2-30 | Py3.8 and 3.9. |
+----+------+---------------------------------------------------------+
| 3 | 20 | Protect model admin class option values from accidental |
| .2 | 20-1 | modification. |
| .1 | 2-30 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Support for invoking admin actions by right clicking |
| .2 | 20-1 | on id
column headers. |
| .0 | 2-30 | | Fix various filter issues. |
| | | | Don\'t show id
on models that don\'t have an id
|
| | | field. |
| | | | Show \"less than\", \"greater than\" etc as \"\<\", |
| | | \">\", etc. |
| | | | Mouse hover tooltip help for date and datetime filter |
| | | values. |
| | | | Filters with bad fields and lookups are reported as |
| | | errors rather than being ignored. |
| | | | Bad filters on public saved View\'s now result in a |
| | | 400 when loading the public URL. |
| | | | Fix issue filtering on aggregated annotations. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Fix UUID\'s not being filterable. |
| .1 | 20-1 | | Fix right click drill and filter trying to filter |
| .4 | 2-19 | unfilterable fields. |
| | | | Fix spurious 0
appearing below numeric 0
filter |
| | | values. |
| | | | Add an extrahead
block to the template and |
| | | documentation for overriding CSS. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Relative time support in date and time filters. |
| .1 | 20-1 | | Show parsed dates and datetimes next to filters. |
| .3 | 2-13 | | Add view SQL link on front page. Contributed by |
| | | #xinye1 |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Remove length function from UUID\'s. |
| .1 | 20-1 | | FK\'s with no admin are exposed as just the FK field. |
| .2 | 2-09 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | Don\'t run the 3.0.0 data migration when there are no |
| .1 | 20-1 | saved views. |
| .1 | 2-01 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | Add right click menu with filter and drill down |
| .1 | 20-1 | options. |
| .0 | 1-29 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | Ignore admins for things that are not Models. |
| .0 | 20-1 | |
| .4 | 1-28 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | Fix exception when filtering to out of bounds year |
| .0 | 20-1 | values. |
| .3 | 1-22 | |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Fix bug with aggregating around is null
values on |
| .0 | 20-1 | Django 3.1. |
| .2 | 1-18 | | Fix is null
returning None for missing fields in |
| | | JsonFields. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | Add get_*
functions for the ddb_*
admin options. |
| .0 | 20-1 | | Add length function to string fields. |
| .1 | 1-12 | | Add support for DB query explain via .explain
url. |
| | | | Prevent exception when getting SQL view of pure |
| | | aggregates. |
| | | | Fix incorrect handling of ISO dates whose day portion |
| | | is less than 13. |
| | | | Python 3.9 support. |
+----+------+---------------------------------------------------------+
| 3 | 20 | | The format of ddb_default_filters has changed. |
| .0 | 20-1 | | Path and prettyPath have been removed from fields and |
| .0 | 1-09 | filters on JSON responses. |
| | | | Choice and is null
fields use human readable values |
| | | in filters. |
| | | | Choice fields have a raw sub field for accessing the |
| | | underlying values. |
| | | | Starts with, regex, etc have been removed form choice |
| | | fields, equivalents are on raw. |
| | | | Verbose_names and short_descriptions are used for |
| | | display in the web frontend and CSV. |
| | | | Equals and not equals for JSON and arrays. |
| | | | JSON field filter supports lists and objects. |
| | | | Array values are now JSON encoded across the board. |
| | | | Backfill saved views for above changes to filter |
| | | formats. |
| | | | Pickup calculated fields on inlines when there is no |
| | | actual admin. |
| | | | Fix bug where ID\'s and annotations on inlines were |
| | | visible to users without perms. |
| | | | Support for aggregation and functions on annotated |
| | | fields. |
| | | | Annotations now respect ddb_hide. |
| | | | Admin links to the Data Browser respect ddb_ignore. |
+----+------+---------------------------------------------------------+
| 2. | 20 | Reject ambiguous date and datetime values in filters. |
| 2. | 20-1 | |
| 21 | 1-02 | |
+----+------+---------------------------------------------------------+
| 2. | 20 | Fix bug with ArrayField
on Django>=3.0 |
| 2. | 20-1 | |
| 20 | 0-22 | |
+----+------+---------------------------------------------------------+
| 2. | 20 | Support for annotations on inlines. |
| 2. | 20-1 | |
| 19 | 0-19 | |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Support for profiling CSV etc output. See |
| 2. | 20-1 | CONTRIBUTING.rst |
| 18 | 0-18 | | Performance improvements for large result sets. |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Performance improvements for large result sets. |
| 2. | 20-1 | | Fix error when choices field has an unexpected value. |
| 17 | 0-15 | |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Fix being unable to reorder aggregates when there is |
| 2. | 20-0 | no pivot. |
| 16 | 9-28 | | Fix back button sometimes not remembering column |
| | | reorderings. |
| | | | Fix reordering columns while a long reload is in |
| | | progress causes an error. |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Handle callables in ModelAdmin.list_display. |
| 2. | 20-0 | | Add data_browser.helpers.attributes
. |
| 15 | 9-27 | | Deprecated @ddb_hide
in favor of |
| | | @attributes(ddb_hide=True)
. |
| | | | Render safestrings returned by calculated fields as |
| | | HTML. |
| | | | Respect the boolean
attribute on calculated fields. |
| | | | Aside from declared booleans, calculated fields now |
| | | always format as strings. |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Saved view style tweaks. |
| 2. | 20-0 | | Only reload on field delete when it might change the |
| 14 | 9-20 | results. |
| | | | Add UI controls for reordering fields. |
+----+------+---------------------------------------------------------+
| 2. | 20 | | Add .sql
format to show raw SQL query. |
| 2. | 20-0 | | Min and max for date and datetime fields. |
| 13 | 9-13 | | Add ddb_default_filters. |
| | | | Integrated cProfile support via .profile
and |
| | | .pstats
. |
+----+------+---------------------------------------------------------+
| 2. | 20 | | DurationField support. |
| 2. | 20-0 | | Sort newly added date (etc) fields by default. |
| 12 | 9-09 | | Fix JSONField support when psycopg2 is not installed. |
| | | | Fix bug with number formatting and pivoted data. |
| | | | Fix error with multiple non adjacent filters on the |
| | | same field. |
| | | | Fix error with naive DateTimeFields. |
+----+------+---------------------------------------------------------+
| 2. | 20 | Minor enhancements and some small fixes. |
| 2. | 20-0 | |
| 11 | 8-31 | |
+----+------+---------------------------------------------------------+
| 2. | 20 | Minor enhancements. |
| 2. | 20-0 | |
| 10 | 8-31 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Small fixes. |
| .2 | 20-0 | |
| .9 | 8-25 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Small fixes. |
| .2 | 20-0 | |
| .8 | 8-23 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Small fixes. |
| .2 | 20-0 | |
| .7 | 8-22 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Basic JSONField support. |
| .2 | 20-0 | |
| .6 | 8-16 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Bug fix. |
| .2 | 20-0 | |
| .5 | 8-01 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | | Additional field support. |
| .2 | 20-0 | | Minor features and bug fixes. |
| .4 | 8-01 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | File and Image field support |
| .2 | 20-0 | |
| .3 | 7-31 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Better support for choice fields. |
| .2 | 20-0 | |
| .2 | 7-26 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Performance tweaks. |
| .2 | 20-0 | |
| .1 | 7-25 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Sort and filter annotated fields. |
| .2 | 20-0 | |
| .0 | 7-21 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Minor bug fixes. |
| .1 | 20-0 | |
| .2 | 7-11 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | | Bug fixes. |
| .1 | 20-0 | | The representation of empty pivot cells has changed |
| .1 | 7-06 | in the JSON. |
+----+------+---------------------------------------------------------+
| 2 | 20 | | Bring views into the JS frontend. |
| .1 | 20-0 | | Implement row limits on results. |
| .0 | 7-06 | | All existing saved views will be limited to 1000 |
| | | rows. |
| | | | Better loading and error status indication. |
| | | | Lock column headers. |
+----+------+---------------------------------------------------------+
| 2 | 20 | Bug fixes. |
| .0 | 20-0 | |
| .5 | 6-20 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Fix Py3.6 support. |
| .0 | 20-0 | |
| .4 | 6-18 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Improve filtering on aggregates when pivoted. |
| .0 | 20-0 | |
| .3 | 6-14 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Improve fonts and symbols. |
| .0 | 20-0 | |
| .2 | 6-14 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | Improve sorting when pivoted. |
| .0 | 20-0 | |
| .1 | 6-14 | |
+----+------+---------------------------------------------------------+
| 2 | 20 | | Pivot tables. |
| .0 | 20-0 | | All public view URL\'s have changed. |
| .0 | 6-14 | | The JSON data format has changed. |
+----+------+---------------------------------------------------------+
| 1 | 20 | Bug fixes. |
| .2 | 20-0 | |
| .6 | 6-08 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Bug fixes. |
| .2 | 20-0 | |
| .5 | 6-08 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Calculated fields interact better with aggregation. |
| .2 | 20-0 | |
| .4 | 6-03 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | JS error handling tweaks. |
| .2 | 20-0 | |
| .3 | 6-02 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Minor fix. |
| .2 | 20-0 | |
| .2 | 6-01 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Improved date handling. |
| .2 | 20-0 | |
| .1 | 5-31 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Support for date functions \"year\", \"month\" etc and |
| .2 | 20-0 | filtering based on \"now\". |
| .0 | 5-31 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Stronger sanitizing of URL strings. |
| .1 | 20-0 | |
| .6 | 5-24 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Fix bug aggregating time fields. |
| .1 | 20-0 | |
| .5 | 5-23 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Fix breaking bug with GenericInlineModelAdmin. |
| .1 | 20-0 | |
| .4 | 5-23 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Cosmetic fixes. |
| .1 | 20-0 | |
| .3 | 5-23 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Cosmetic fixes. |
| .1 | 20-0 | |
| .2 | 5-22 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Cosmetic fixes. |
| .1 | 20-0 | |
| .1 | 5-20 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Aggregate support. |
| .1 | 20-0 | |
| .0 | 5-20 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Py3.6 support. |
| .0 | 20-0 | |
| .2 | 5-17 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Small fixes. |
| .0 | 20-0 | |
| .1 | 5-17 | |
+----+------+---------------------------------------------------------+
| 1 | 20 | Initial version. |
| .0 | 20-0 | |
| .0 | 5-17 | |
+----+------+---------------------------------------------------------+