Neapolitan with namespaces - Django CRUD views
This project has been archived.
The maintainers of this project have marked this project as archived. No new releases are expected.
Project description
Nominopolitan
This is an opinionated extension package for the excellent neapolitan package.
It is a very early alpha release. No tests. Limited docs. Expect many breaking changes. You might prefer to just fork or copy and use whatever you need. Hopefully some features may make their way into neapolitan over time.
Dependencies
neapolitan(obviously - see installation section below)bootstrap5unless you want to override the css framework and templatesjavascriptfor many of the featureshtmxif you want to use htmx ;)django-crispy-formsandcrispy-bootstrap5- For enhanced form styling (ifuse_crispy=True)bootstrap5- Default CSS framework (unless overridden)htmx- Required in your base template ifuse_htmx=Truepopper.js- Required for table column text truncation popovers
Features
Namespacing
- Namespaced URL handling
namespace="my_app_name"
Templates
- Allow specification of
base_template_path(to yourbase.htmltemplate) - Allow override of all
nominopolitantemplates by specifyingtemplates_path - Management command
nm_mktemplateto copy requirednominopolitantemplate (analagous toneapolitan'smktemplate)
Display
- Display related field name (using
str()) in lists and details (instead of numeric id) - Header title context for partial updates (so the title is updated without a page reload)
Extended fields and properties attributes
fields=<'__all__' | [..]>to specify which fields to include in list viewproperties=<'__all__' | [..]>to specify which properties to include in list viewdetail_fieldsanddetail_propertiesto specify which to include in detail view- Support exclusions via
exclude,exclude_properties,detail_exclude,detail_exclude_properties - Support for
extra_actionsto add additional actions to list views
Filtersets
object_list.htmlstyled for bootstrap to show filters.- if
filterset_fieldsis specified, style with crispy_forms if present and set htmx attributes if applicable - if
filterset_classis provided, then option to subclassHTMXFilterSetMixinand useself.setup_htmx_attrs()in__init__() - You can now override the method
get_filter_queryset_for_field(self, field_name, model_field)to restrict the available options for a filter field.-
field_name: The name of the field being filtered (str) -
model_field: The actual Django model field instance (e.g., ForeignKey, CharField) -
For example, if you're already restricting the returned objects by overriding
get_queryset(), then you want the filter options for foreign key fields to also be subject to this restriction. -
So you can override
get_filter_queryset_for_field()to return the queryset for the field, but filtered by the same restriction as your overriddenget_queryset()method.# Example of overrides of get_queryset and get_filter_queryset_for_field # def get_queryset(self): # qs = super().get_queryset() # qs = qs.filter(author__id=20) # return qs.select_related('author') # def get_filter_queryset_for_field(self, field_name, model_field): # """Override to restrict the available options if the field is author. # """ # qs = super().get_filter_queryset_for_field(field_name, model_field) # print(field_name) # if field_name == 'author': # qs = qs.filter(id=20) # return qs
-
htmx and modals
- Support for rendering templates using
htmx - Support for modal display of CRUD view actions (requires
htmx-- and Alpine for bulma) - htmx supported pagination (requires
use_htmx = True) for reactive loading - Support to specify
hx_triggerand setresponse['HX-Trigger']for every response
Styled Templates
- Supports
bootstrap5(default framework). To use a different CSS framework:- Set
NOMINOPOLITAN_CSS_FRAMEWORK = '<framework_name>'insettings.py - Create corresponding templates in your
templates_pathdirectory - Override
NominopolitanMixin.get_framework_styles()in your view to add your framework's styles,
set theframeworkkey to the name of your framework and add the required values.
- Set
Forms
- if
form_classis not specified, then non-editable fields are automatically excluded from forms - Optional
create_form_classfor create operations:- Allows a separate form class specifically for create views
- Useful when create and update forms need different: Field sets, Validation logic, Base classes
- Falls back to
form_classif not specified
- Support for
crispy-formsif installed in project anduse_crispyparameter is notFalse- make sure you have
crispy_bootstrap5also installed if you want - if you have set up a different library use the correct crispy package (eg
crispy_bulma,crispy_tailwind)
- make sure you have
Styled Table Options
-
set
table_font_size, measured inrem.- eg
table_font_size = 0.875. (default = 1, set inget_table_font_size()) - This will be applied to buttons, filters and the table data itself using the custom style in
object_list.html:.table-font-size {font-size: {{ table_font_size }};}.
- eg
-
set
table_max_col_widthas a parameter, measured inch(ie number of0characters in the current font).- eg
table_max_col_width = 10(default = 25, set inget_table_max_col_width()) - limit the width of the column to these characters and truncate the data text if needed.
- if a field is truncated, a popover will be shown with the full text (requires
popper.jsbe installed) - column headers will be wrapped to the width of the column (as determined by width of data items)
- eg
-
to calculate the maximum height of the
object_listtable, we allow setting of 2 parameters:table_pixel_height_other_page_elements, expressed in pixels (default = 0, set inget_table_pixel_height_other_page_elements())table_max_height: (default = 70, set inget_table_max_height())- expressed as vh units (ie percentage) of the remaining blank space after subtracting
table_pixel_height_other_page_elements
- expressed as vh units (ie percentage) of the remaining blank space after subtracting
- In the partial
list.htmlthese parameters are used to calculatetable-max-heightas below:
<style> .table-max-height { /* max-height: {{ table_max_height }}; */ max-height: calc((100vh - {{ table_pixel_height_other_page_elements }}) * {{ table_max_height }} / 100); } </style>
- You can tune these parameters depending on the page that the table is appearing on to get the right table height.
- crazy right?.
Table Sorting
- click table header to toggle sorting direction (columns start off unsorted)
- the method always includes a secondary sort by primary key for stable pagination
- will use
htmxifuse_htmx is True - current
list.htmltemplate will display bootstrap icons (if installed) for sorting direction:- you must install bootstrap icons to use this feature
- if filter options are set, the returned queryset will be sorted and filters
- current issue where if filters are displayed and you sort, the filters are hidden; just redisplay them with the button
sample App
sampleapp is a simple example of how to usedjango_nominopolitan. It's available in the repository and not part of the package.- it includes management commands
create_sample_dataanddelete_sample_data
Management Commands
-
nm_mktemplate:-
This is the same as
neapolitan'smktemplatecommand except it copies from thenominopolitantemplates instead of theneapolitantemplates. -
It's the same syntax as
neapolitan'smktemplatecommand:python manage.py nm_mktemplate <app_name>.<model_name> --<suffix>
-
-
nm_clear_session_keys- Used to clear all user session keys related to nominopolitan
-
nm_help- Displays the Nominopolitan README.md documentation in a paginated format
--linesto specify number of lines to display per page (default: 20)--allto display entire content without pagination
Installation
With pip:
pip install django-nominopolitan
Poetry:
poetry add django-nominopolitan
Configuration
Add these to your settings.py:
INSTALLED_APPS = [
...
"nominopolitan", # put this before neapolitan
"neapolitan", # this is required to use the `NominopolitanMixin`
...
]
In addition:
- If you want to set
use_htmx = True, then make surehtmxis installed in your base template anddjango_htmxis installed. - If you want to set
use_modal = True, it requiresuse_htmx=True(see above) andalpinejsis installed in your base template.
Usage
The best starting point is neapolitan's docs. The basic idea is to specify model-based CRUD views using:
# neapolitan approach
class ProjectView(CRUDView):
model = projects.models.Project
fields = ["name", "owner", "last_review", "has_tests", "has_docs", "status"]
The nominopolitan mixin adds a number of features to this. The values below are indicative examples.
from nominopolitan.mixins import NominopolitanMixin
from neapolitan.views import CRUDView
class ProjectCRUDView(NominopolitanMixin, CRUDView):
# *******************************************************************
# Standard neapolitan attributes
model = models.Project
fields = [
"name", "project_owner", "project_manager", "due_date",
]
form_class = forms.ProjectForm # standard neapolitan setting if needed
# ...other standard neapolitan attributes
# ******************************************************************
# nominopolitan attributes
# which fields and properties to include in the list view
fields = '__all__' # if you want to include all fields
# you can omit the fields attribute, in which case it will default to '__all__'
exclude = ["description",] # list of fields to exclude from list
properties = ["is_overdue",] # if you want to include @property fields in the list view
# properties = '__all__' if you want to include all @property fields
properties_exclude = ["is_overdue",] # if you want to exclude @property fields from the list view
# sometimes you want additional fields in the detail view
detail_fields = ["name", "project_owner", "project_manager", "due_date", "description",]
# or '__all__' to use all model fields
# or '__fields__' to use the fields attribute
# if you leave detail_fields to None, it will default be treated as '__fields__'
detail_exclude = ["description",] # list of fields to exclude from detail view
detail_properties = '__all__' # if you want to include all @property fields
# or a list of valid properties
# or '__properties__' to use the properties attribute
detail_properties_exclude = ["is_overdue",] # if you want to exclude @property fields from the detail view
namespace = "my_app_name" # specify the namespace
# if your urls.py has app_name = "my_app_name"
# filtersets
filterset_fields = ["name", "project_owner", "project_manager", "due_date",]
# this is a standard neapolitan parameter, but nominopolitan converts this
# to a more elaborate filterset class
# Forms
use_crispy = True # will default to True if you have `crispy-forms` installed
# if you set it to True without crispy-forms installed, it will resolve to False
# if you set it to False with crispy-forms installed, it will resolve to False
create_form_class = forms.ProjectCreateForm # if you want a separate create form
# the update form always uses form_class
# Templates
base_template_path = "core/base.html" # defaults to inbuilt "nominopolitan/base.html"
templates_path = "myapp" # if you want to override all the templates in another app
# or include one of your own apps; eg templates_path = "my_app_name/nominopolitan"
# and then place in my_app_name/templates/my_app_name/nominopolitan
# table display parameters
table_pixel_height_other_page_elements = 100 # this will be expressed in pixels
table_max_height = 80 # as a percentage of remaining viewport height
table_font_size = '1.05' # expressed as rem
table_max_col_width = '25' # expressed as `ch` (characters wide)
# htmx & modals
use_htmx = True # if you want the View, Detail, Delete and Create forms to use htmx
# if you do not set use_modal = True, the CRUD templates will be rendered to the
# hx-target used for the list view
# Requires:
# htmx installed in your base template
# django_htmx installed and configured in your settings
hx_trigger = 'changedMessages' # Single event trigger (strings, numbers converted to strings)
# Or trigger multiple events with a dict:
# hx_trigger = {
# 'changedMessages': None, # Event without data
# 'showAlert': 'Success!', # Event with string data
# 'updateCount': 42 # Event with numeric data
# }
# hx_trigger finds its way into every response as:
# request['HX-Trigger'] = self.get_hx_trigger() in self.render_to_response()
# valid types are (str, int, float, dict)
# but dict must be of form {k:v, k:v, ...} where k is a string and v can be any valid type
use_modal = True #If you want to use the modal specified in object_list.html for all action links.
# This will target the modal (id="nominopolitanModalContent") specified in object_list.html
# Requires:
# use_htmx = True
# Alpine installed in your base template
# htmx installed in your base template
# django_htmx installed and configured in your settings
modal_id = "myCustomModalId" # Allows override of the default modal id "nominopolitanBaseModal"
modal_target = "myCustomModalContent" # Allows override of the default modal target
# which is #nominopolitanModalContent. Useful if for example
# the project has a modal with a different id available
# eg in the base template. This is where the modal content will be rendered.
# extra actions (extra buttons for each record in the list)
extra_actions = [ # adds additional actions for each record in the list
{
"url_name": "fstp:do_something", # namespace:url_pattern
"text": "Do Something",
"needs_pk": False, # if the URL needs the object's primary key
"hx_post": True, # use POST request instead of the default GET
"button_class": "is-primary", # semantic colour for button (defaults to "is-link")
"htmx_target": "content", # htmx target for the extra action response
# (if use_htmx is True)
# NB if you have use_modal = True and do NOT specify htmx_target, then response
# will be directed to the modal
"display_modal": False, # when use_modal is True but for this action you do not
# want to use the modal for whatever is returned from the view, set this to False
# the default if empty is True
},
]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_nominopolitan-0.1.9.tar.gz.
File metadata
- Download URL: django_nominopolitan-0.1.9.tar.gz
- Upload date:
- Size: 30.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.12.9 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fac2b9e217db068b0f4e69efb6aaf10f92673836c13ee6700c01248833b8dc60
|
|
| MD5 |
a1cfd70b89b2a37f95aec6bd6a6dedf5
|
|
| BLAKE2b-256 |
8e98fa28f5d2ad50c8f22d9f61de4488c160263b8ac9230a60e1a8366991855a
|
File details
Details for the file django_nominopolitan-0.1.9-py3-none-any.whl.
File metadata
- Download URL: django_nominopolitan-0.1.9-py3-none-any.whl
- Upload date:
- Size: 32.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.12.9 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a9476e41eb47f9b1c1bc80d8047332c9f5b3043c28089ccdf24f2b289e97bd3
|
|
| MD5 |
4d05208fdb45412c5f06d05cf8b0b62d
|
|
| BLAKE2b-256 |
851574d45c052b561bdaa0fe3bd81baa908fc9f8899fb5dbb4dbfbad43f576e1
|