Package: django-data-browser
Interactive, user-friendly database explorer.ContentsDemoFeaturesSupported VersionsInstallationSettingsPermissionsSecuritySentryLinking to the Data BrowserSpecifying models and fieldsCalculated and Annotated fieldsPerformanceStyle customizationCustom functions and aggregationsAdmin SiteVersion numbersRelease HistoryDemoThere is a live demo site available herehttps://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/.FeaturesZero 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 VersionsThe Data Browser is currently tested on:Django 3.2 - 5.0Python 3.8 - 3.12MySQL, PostgreSQL, SQLiteWe highly recommend and only officially support the latest patch release of each Python and Django series.InstallationRunpip installdjango-data-browser.Add"data_browser"to installed_apps.Addpath("data-browser/",include("data_browser.urls"))to your urls.Runpython manage.py migrate.If you have queryset annotations in your admin or are interested in exposing calculated values see theCalculated and Annotated fieldssection.SettingsNameDefaultDocs SectionFunctionDATA_BROWSER_ADMIN_FIELD_NAMEadminSet the name for the “open in Django admin” field.DATA_BROWSER_ALLOW_PUBLICFalseSecurityAllow selected saved views to be accessed without admin login in limited circumstances.DATA_BROWSER_AUTH_USER_COMPATTruePerformanceWhen callingget_fieldsetson aUserAdminalways pass an instance of the associated model.DATA_BROWSER_DEFAULT_ROW_LIMIT1000The default value for the row limit selector in the UI.DATA_BROWSER_DEVFalseCONTRIBUTING.rstEnable proxying frontend to JS dev server.DATA_BROWSER_FE_DSNNoneSentryThe DSN the frontend sentry should report to, disabled by default.DATA_BROWSER_USING_DB"default"PerformanceSpecify a database alias to use by default on all database queries.DATA_BROWSER_ADMIN_OPTIONS{}Specifying models and fieldsSet admin specific configuration options.DATA_BROWSER_APPS_EXPANDEDTrueAre the app sections of the homepage model list expanded by default.DATA_BROWSER_ADMIN_SITENoneAdmin SiteSpecify anadmin.AdminSiteto use (default isadmin.site).Permissionsdata_browser.make_view_publicSecurityCan make a saved view publicly available.data_browser.share_viewCan share a saved view with other users.SecurityMost 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 permissiondata_browser | view | Can make a saved view publically availableto 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 valueDATA_BROWSER_ALLOW_PUBLIC.SentryThe frontend code has builtin Sentry support, it isdisabled by default. To enable it set the Django settings valueDATA_BROWSER_FE_DSN, for example to set it to the Data Browser project Sentry use:DATA_BROWSER_FE_DSN="https://af64f22b81994a0e93b82a32add8cb2b@o390136.ingest.sentry.io/5231151"Linking to the Data BrowserThe home page URL of the Data Browser is given byreverse("data_browser:home").Additionally if you are usingdata_browser.helpers.AdminMixinthen in Admin list views the URL of the Data Browser page for the same model is available as the template context variableddb_url.One convenient way of utilizing this is to create the filetemplates/admin/change_list_object_tools.htmland populate it with:{% extends "admin/change_list_object_tools.html" %}
{% block object-tools-items %}
    {{ block.super }}
    {% if ddb_url %}<li><ahref="{{ 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 fieldsBy 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 onModelAdmins andInlines.NameFormatPurposeddb_ignoreget_ddb_ignore(request)boolIgnore this Admin / Inline entirely, will still show fields from other Inlines / Admins on the same model.ddb_hide_fieldsget_ddb_hide_fields(request)[field_name]Explicitly hide the specified fields.ddb_extra_fieldsget_ddb_extra_fields(request)[field_name]Add additional fields that are not mentioned in fields, fieldsets or list_display.ddb_json_fieldsget_ddb_json_fields(request){field_name: {json_field_name: type}}Expose fields within JSON data for access in the Data Browser. Type can be “string”, “number” or “boolean”.ddb_default_filtersget_ddb_default_filters()[(path, lookup, value)]Default filters to be added when opening this model.E.G. to addclient__name__equals=Testuse[("client__name","equals","Test")].ddb_action_urlget_ddb_action_url(request)strThe url to post admin actions to, usually the changelist view. SeeAdmin ActionsThese can also be set via the settings entryDATA_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 theddb_hideattribute and annotated fields are always visible unless explicitly hidden.Calculated and Annotated fieldsCalculatedCalculated fields are fields on theModelAdminwhose value comes from a function on theModelAdminor a function or property on the Model itself, as described at the bottom of theDjango 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 attributeddb_hidetoTrue. Thedata_browser.helpers.attributesdecorator can make this a little tidier.@attributes(ddb_hide=True)defmy_calculated_field(self,obj):return...AnnotatedThe Data Browser has additional support for annotated fields. Normally you would expose these as calculated fields. The moduledata_browser.helperscontains 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.Mixdata_browser.helpers.AdminMixininto your ModelAdmin.Add a function decorated withdata_browser.helpers.annotationthat takes and updates a queryset.fromdata_browser.helpersimportAdminMixin,annotation@admin.register(MyModel)classMyAdmin(AdminMixin,ModelAdmin):fields=["my_field"]@annotationdefmy_field(self,request,qs):returnqs.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 haveoutput_fieldset 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 theadmin_order_fieldandbooleanproperties andreadonly_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 inlist_displaythis 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 inddb_hide_fields.Performanceget_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 callget_queryset()on theModelAdminof 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 callget_queryset()on the relevantModelAdmins 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 callget_queryset()on their associatedModelAdmins. These calls are aggregated so it will only make one per model.As a simple example, if you did a query against theBookmodel for the fields:book.namebook.author.namebook.author.agebook.author.number_of_booksbook.publisher.nameWhere theauthor.ageis actually a property on theAuthormodel, andauthor.number_of_booksis an@annotationon theAuthorModelAdmin, 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 thepkspassed to in_bulk in the second query came fromauthor__idin the first.You can view an approximation of the main queryset by changing the.htmlin the URL to.qs. In a similar manner.sql,.explainand.analyzeare also available.When the Data Browser calls the adminget_queryset()functions it will put some context inrequest.data_browser. This allows you to test to see if the Data Browser is making the call as follows:ifhasattr(request,"data_browser"):# Data Browser specific customizationThis 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 seeQuerySet.using()below.).The context also includes afieldsmember 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(nothasattr(request,"data_browser")or"my_field"inrequest.data_browser["fields"]):# do prefetching and annotating associated with my_fieldThe AdminMixin described in theCalculated and Annotated fieldssection is doing this internally for@annotationfields.QuerySet.using()The settingDATA_BROWSER_USING_DBcan be used to direct Data Browser initiated database queries to a replica. Underneath the value of this is passed intoQuerySet.using().ModelAdmin.get_fieldsets()The Data Browser also callsget_fieldsetsto find out what fields the current user can access.As withget_querysetthe Data Browser will setrequest.data_browserwhen callingget_fieldsetsand 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 callingget_fieldsetson a subclass ofdjango.contrib.auth.admin.UserAdminthe Data Browser will pass a newly constructed instance of the relevant model. This behavior can be disabled by settingsettings.DATA_BROWSER_AUTH_USER_COMPATtoFalse.Admin ActionsDjango’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 setrequest.data_browserlike it normally would. Instead it will set the post argumentdata_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 specifyget_ddb_action_urlto 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 customizationYou can override thedata_browser/index.htmltemplate perDjangoâ€™s template overriding docs, and replace theextraheadblock.
(Ensure"data_browser"is after your app inINSTALLED_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 aggregationsIt is possible to register additional functions and aggregations with the Data Browser, including custom ones.TypesFunctions and Aggregations are attached to the Data Browsers core types, these are indata_browser.types.FunctionsThis functionality is provisional and not subject to normal backward compatible guarantees.The function registry is indata_browser.orm_functions.TYPE_FUNCTIONSthis has typedict[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:fromdjango.db.models.functionsimportMD5fromdata_browser.typesimportStringTypefromdata_browser.orm_functionsimportFunc,TYPE_FUNCTIONSTYPE_FUNCTIONS[StringType]["md5"]=Func(MD5,StringType)AggregatesThis functionality is provisional and not subject to normal backward compatible guarantees.The aggregate registry is indata_browser.orm_aggregates.TYPE_AGGREGATESthis has typedict[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:fromdjango.db.modelsimportCountfromdata_browser.typesimportNumberTypefromdata_browser.orm_aggregatesimportAgg,TYPE_AGGREGATESTYPE_AGGREGATES[NumberType]["full_count"]=Agg(lambdax:Count(x,distinct=False),NumberType)Custom SQL exampleFor a larger example imagine you wanted to use Postgres’spercentile_contfunctionality to add ap95aggregate to duration fields, perhaps for some kind of application performance monitoring usecase.First we need to explainpercentile_contto Django.fromdjango.db.modelsimportAggregateclassPercentile(Aggregate):arity=1function="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 wantp95on duration fields.fromdata_browser.orm_aggregatesimportTYPE_AGGREGATES,Aggfromdata_browser.typesimportDurationTypeTYPE_AGGREGATES[DurationType]["p95"]=Agg(lambdax:Percentile(0.95,x),DurationType)Admin SiteYou can create and use a customadmin.AdminSite(seehttps://docs.djangoproject.com/en/4.2/ref/contrib/admin/).To do so, in yoursettings.py, add:fromdjango.contribimportadminclassBrowserAdminSite(admin.AdminSite):passDATA_BROWSER_ADMIN_SITE=BrowserAdminSite(name='data_browser')Then, in anyadmin.py, register the models as usually but usingDATA_BROWSER_ADMIN_SITE.For instance inmyapp/admin.py:fromdjango.contribimportadminfromdjango.confimportsettingsfrommyapp.modelsimportMyAdminModel,MyBrowsableModel# register in admin onlyadmin.register(MyAdminModel)# register in data browser onlysettings.DATA_BROWSER_ADMIN_SITE.register(MyBrowsableModel)Version numbersThe Data Browser uses the standardMajor.Minor.Patchversion 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 therequest.data_browserpassed toget_fieldsetsandget_queryset.Existing saved views.The URL’s of public saved views.For alpha and beta releases absolutely anything may change / break.Release HistoryVersionDateSummary4.2.82024-02-11Improve field filter matching.Add sticky headers to the field list.4.2.72024-02-04Add a text filter to the top of the field list.4.2.62024-02-04Support custom admin sites. Contributed by #aboutofplutoFix 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.2.52023-07-20Fix parsing of date/datetime strings likemon-1.Add support for DB query analyze via.analyzeurl, similar to the existing.explain.4.2.42023-07-02Provisional support for adding custom functions and aggregations.Fixallaggregate on booleans and durations. (Postgres only)4.2.32023-06-15Fix ASGI compatibility issue.4.2.22023-06-08Fix various issues around saved view validity.4.2.12023-05-21BREAKING: In JSON format moveparsedandfitlerErrorsonto the filters.Display invalid fields (previously they were ignored).Fix small bug when removing filters with errors.4.1.12023-05-07Fix bug with shared views when using multiple authentication backends.4.1.02023-05-01Support sharing of saved views between users.Allow mixing of folders and views in the saved views section.Fix bug where an invalid filter causes the query page to fail to render.4.0.172023-04-25Fix bug with admin actions only working on the first column (introduced in 4.0.14).4.0.162023-04-16Group homepage model list into collapsible sections by app.Allow grouping saved views into collapsible folders.4.0.152023-04-11Clear confirm prompts after a short delay.Remember the current saved view and allow updating it.4.0.142023-04-05Fix bug with admin actions not respecting ordering when the number of results exceeds the limit.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.0.132023-03-06Add support for Django 4.1.Work with CSRF_COOKIE_HTTPONLY which is enabled by cookiecutter-django.4.0.122022-05-03Allow setting the per admin options viaDATA_BROWSER_ADMIN_OPTIONS.4.0.112022-04-12Fix bug whenDATA_BROWSER_ADMIN_FIELD_NAMEcontains spaces.4.0.102022-04-10Make results stable by always sorting all fields.Fix an issue with few to no results when pivoted and the headers exceed the result limit.Add support for Postgres’s array length function.Allow overriding the “open in Django admin” field name withDATA_BROWSER_ADMIN_FIELD_NAME.Add an AppConfig and declare thedefault_auto_field.Expose access toQuerySet.using()via a newDATA_BROWSER_USING_DBsetting.4.0.92022-01-04Fix contains filter not working on files and URLs.Allow combining literal date time values with relative clauses.Expose Postgres’sArrayAggas anallaggregate.Add mouse over text for the “to many” icon.Fix issue whenrelated_nameis different fromrelated_query_nameCSS tweaks.Change calculated field red to grey.Add support for Django 4.0 and Python 3.10 drop support for Python 3.6.4.0.82021-12-12Fix formatting ofFexpressions when using.qs.Make the field list and filter list collapsible.CSS tweaks.Add public view info torequest.data_browser.Fix crash when length filtering arrays of choice fields.4.0.72021-08-16Add support for django-hashid-field.Fix a crash bug when aggregating fields with names starting with_.4.0.62021-08-10Fix spelling mistake.4.0.52021-08-09Don’t override right click context menu for HTML values (e.g. “Admin” columns).Fix “bad lookup” when excludingIsNull/NotNullvalues.Fix pressing enter clearing all filters.Fix exceptions when using.qs.Fix view link on Saved View admin page not preservinglimit.Improve placement of context menus.4.0.42021-07-04Add.qsformat support to see the main Django Queryset.Supportweeksin 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.0.32021-06-18Test on Django 3.2.4.0.22021-04-12URL, image and file fields filter like strings and render as strings in CSV and JSON.4.0.12021-04-11URLFields display as links.Change pivot icon.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.0.02021-03-13In the JSON output aggregate fields are now always in the body.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.3.02021-02-19Drop support for Django 2.0 and 2.1Rework Admin action integration.3.2.52021-02-07Date filter values formated as2020-1-2are now considered ISO ordered and no longer ambiguous.Rework @annotation and AdminMixin so @annotation can be used on mixins.3.2.42021-02-02Fixequalsandnot equalsnot working for array fields.Improve date and datetime filter errors.Improve and contrast display of null and empty string.Various fixes for models where the primary key is notid.Empty but non null file fields render as empty string instead of null.Fixis nullnot working with theyearfunction.The field list is now sorted by display name (except for the primary key and admin link).Fixnot equalsexcluding nulls with functions and aggregates, e.g.year,minetc.Right click filter and drill down now correctly handle null values.Prevent exception when a saved views name gets too long.3.2.32021-01-11Fix issue when using a filter with a different type from the field, e.g.is null.3.2.22020-12-30Fixidfield missing from some models.Per Django, Django 2.0 & 2.1 are not supported on Py3.8 and 3.9.3.2.12020-12-30Protect model admin class option values from accidental modification.3.2.02020-12-30Support for invoking admin actions by right clicking onidcolumn headers.Fix various filter issues.Don’t showidon models that don’t have anidfield.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.1.42020-12-19Fix UUID’s not being filterable.Fix right click drill and filter trying to filter unfilterable fields.Fix spurious0appearing below numeric0filter values.Add anextraheadblock to the template and documentation for overriding CSS.3.1.32020-12-13Relative time support in date and time filters.Show parsed dates and datetimes next to filters.Add view SQL link on front page. Contributed by #xinye13.1.22020-12-09Remove length function from UUID’s.FK’s with no admin are exposed as just the FK field.3.1.12020-12-01Don’t run the 3.0.0 data migration when there are no saved views.3.1.02020-11-29Add right click menu with filter and drill down options.3.0.42020-11-28Ignore admins for things that are not Models.3.0.32020-11-22Fix exception when filtering to out of bounds year values.3.0.22020-11-18Fix bug with aggregating aroundis nullvalues on Django 3.1.Fixis nullreturning None for missing fields in JsonFields.3.0.12020-11-12Addget_*functions for theddb_*admin options.Add length function to string fields.Add support for DB query explain via.explainurl.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.0.02020-11-09The format of ddb_default_filters has changed.Path and prettyPath have been removed from fields and filters on JSON responses.Choice andis nullfields 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.2.212020-11-02Reject ambiguous date and datetime values in filters.2.2.202020-10-22Fix bug withArrayFieldon Django>=3.02.2.192020-10-19Support for annotations on inlines.2.2.182020-10-18Support for profiling CSV etc output. See CONTRIBUTING.rstPerformance improvements for large result sets.2.2.172020-10-15Performance improvements for large result sets.Fix error when choices field has an unexpected value.2.2.162020-09-28Fix being unable to reorder aggregates when there is no pivot.Fix back button sometimes not remembering column reorderings.Fix reordering columns while a long reload is in progress causes an error.2.2.152020-09-27Handle callables in ModelAdmin.list_display.Adddata_browser.helpers.attributes.Deprecated@ddb_hidein favor of@attributes(ddb_hide=True).Render safestrings returned by calculated fields as HTML.Respect thebooleanattribute on calculated fields.Aside from declared booleans, calculated fields now always format as strings.2.2.142020-09-20Saved view style tweaks.Only reload on field delete when it might change the results.Add UI controls for reordering fields.2.2.132020-09-13Add.sqlformat to show raw SQL query.Min and max for date and datetime fields.Add ddb_default_filters.Integrated cProfile support via.profileand.pstats.2.2.122020-09-09DurationField support.Sort newly added date (etc) fields by default.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.2.112020-08-31Minor enhancements and some small fixes.2.2.102020-08-31Minor enhancements.2.2.92020-08-25Small fixes.2.2.82020-08-23Small fixes.2.2.72020-08-22Small fixes.2.2.62020-08-16Basic JSONField support.2.2.52020-08-01Bug fix.2.2.42020-08-01Additional field support.Minor features and bug fixes.2.2.32020-07-31File and Image field support2.2.22020-07-26Better support for choice fields.2.2.12020-07-25Performance tweaks.2.2.02020-07-21Sort and filter annotated fields.2.1.22020-07-11Minor bug fixes.2.1.12020-07-06Bug fixes.The representation of empty pivot cells has changed in the JSON.2.1.02020-07-06Bring views into the JS frontend.Implement row limits on results.All existing saved views will be limited to 1000 rows.Better loading and error status indication.Lock column headers.2.0.52020-06-20Bug fixes.2.0.42020-06-18Fix Py3.6 support.2.0.32020-06-14Improve filtering on aggregates when pivoted.2.0.22020-06-14Improve fonts and symbols.2.0.12020-06-14Improve sorting when pivoted.2.0.02020-06-14Pivot tables.All public view URL’s have changed.The JSON data format has changed.1.2.62020-06-08Bug fixes.1.2.52020-06-08Bug fixes.1.2.42020-06-03Calculated fields interact better with aggregation.1.2.32020-06-02JS error handling tweaks.1.2.22020-06-01Minor fix.1.2.12020-05-31Improved date handling.1.2.02020-05-31Support for date functions “year”, “month” etc and filtering based on “now”.1.1.62020-05-24Stronger sanitizing of URL strings.1.1.52020-05-23Fix bug aggregating time fields.1.1.42020-05-23Fix breaking bug with GenericInlineModelAdmin.1.1.32020-05-23Cosmetic fixes.1.1.22020-05-22Cosmetic fixes.1.1.12020-05-20Cosmetic fixes.1.1.02020-05-20Aggregate support.1.0.22020-05-17Py3.6 support.1.0.12020-05-17Small fixes.1.0.02020-05-17Initial version.