The Admin

Django ERP framework Site

Django ERP framework Site is a custom admin site. It provide you the theme and other goodies aimed to make developement of ERP solutions easier. It’s use is optional.

ModelAdmin Classes

A subclass of admin.ModelAdmin with various different options

  1. View page that display all reports about this certain entity / records creating a dashboard out of the box.

  2. Comes with settings in place for reversion

  3. Usually if a User if given a permission on Model, it means that they have same permissions to its inline models. Example: User who can add invoice, is of course permitted to add its inline details. | This option can be switched off by setting permission_override_model on the TransactionInline AdminModel

EntityAdmin offer two important hooks to manage little bit complicated flow

  1. it offer EntityAdmin.pre_save(self, form, formsets, change) It offers you a hook before saving the whole page to do any management you want. Like saving the total of the invoicelines in the Invoice.value field.

  2. whole_changeform_validation(self, request, form, formsets, change, **kwargs)() Where you’ll get a chance to validate the whole page forms and formsets

FK Autocomplete (Select2 / AJAX)

All EntityAdmin subclasses automatically render ForeignKey fields as Select2 AJAX widgets — no manual autocomplete_fields declaration needed.

How it works

Django’s built-in autocomplete_fields uses Select2 and an AJAX endpoint that is registered automatically on each admin class. The framework’s EntityAdmin overrides get_autocomplete_fields() to detect eligible FK fields at runtime:

  • EntityAdmin already declares search_fields = ["name", "slug"], so every registered entity admin is autocomplete-eligible by default.

  • At form render time, each FK field is checked: if the related model’s admin is registered and has search_fields, the field becomes a Select2 widget.

No changes are needed in your own admin classes — it just works.

Fine-tuning

  1. Opt a field out — add its name to autocomplete_exclude_fields:

    class SalesAdmin(TransactionAdmin):
        autocomplete_exclude_fields = ["agent"]  # agent keeps plain <select>
    
  2. Full explicit control — set autocomplete_fields directly; auto-detection is skipped entirely for that admin:

    class SalesAdmin(TransactionAdmin):
        autocomplete_fields = ["client"]  # only client gets Select2
    
  3. Customise what is searchable via AJAX — override search_fields on the related model’s admin (the default ["name", "slug"] covers most cases, but you can extend it):

    @admin.register(Product)
    class ProductAdmin(EntityAdmin):
        search_fields = ["name", "barcode", "sku"]
    

    Setting search_fields = [] on a related admin disables autocomplete for any FK pointing to that model.

Inline support

TransactionItemAdmin (TabularInline) applies the same auto-detection, so inline FK fields (e.g. product, store on movement lines) also render as Select2 widgets. The same autocomplete_exclude_fields attribute and autocomplete_fields override work on inline classes.

EntityAdmin

class erp_framework.admin.admin.EntityAdmin(*args, **kwargs)[source]
changelist_view(request, extra_context=None)[source]

The ‘change list’ admin view for this model.

formfield_for_dbfield(db_field, request, **kwargs)[source]

Hook for specifying the form Field instance for a given database Field instance.

If kwargs are given, they’re passed to the form Field’s constructor.

get_actions(request)[source]

Return a dictionary mapping the names of all actions for this ModelAdmin to a tuple of (callable, name, description) for each action.

get_autocomplete_fields(request)[source]

Auto-enables AJAX autocomplete (Select2) for all FK fields whose related model admin is registered and has search_fields defined.

Fine-tuning options:

  1. Opt a field out — add its name to autocomplete_exclude_fields:

    class SalesAdmin(TransactionAdmin):
        autocomplete_exclude_fields = ["agent"]  # agent stays as plain select
    
  2. Explicit control — set autocomplete_fields directly; auto-detect is skipped:

    class SalesAdmin(TransactionAdmin):
        autocomplete_fields = ["client"]  # only client gets Select2
    
  3. Enable for a related model — add search_fields to its admin (EntityAdmin already has search_fields = ["name", "slug"] so all entity admins are eligible by default):

    @admin.register(Product)
    class ProductAdmin(EntityAdmin):
        search_fields = ["name", "barcode"]  # used by autocomplete AJAX
    
get_list_display(request)[source]

Return a sequence containing the fields to be displayed on the changelist.

post_save(request, new_object, form, formsets, change)[source]

Hook for doing any final logic after saving :param form: :param formsets: :param change: :return:

pre_save(form, formsets, change)[source]

Hook for doing any final computation setting before saving :param form: :param formsets: :param change: :return:

reversion_register(model, **kwargs)[source]

Registers the model with reversion.

save_model(request, obj, form, change)[source]

Given a model instance save it to the database.

whole_changeform_validation(request, form, formsets, change, **kwargs)[source]

A Hook for validating the whole changeform :param form: the ModelAdmin Form :param formsets: inline formsets :param kwargs: extra kwargs :return: True for valid [default] False for Invalid

TransactionAdmin

class erp_framework.admin.admin.TransactionAdmin(*args, **kwargs)[source]
formfield_for_dbfield(db_field, request, **kwargs)[source]

Hook for specifying the form Field instance for a given database Field instance.

If kwargs are given, they’re passed to the form Field’s constructor.

get_list_filter(request)[source]

Return a sequence containing the fields to be displayed as filters in the right sidebar of the changelist page.

save_formset(request, form, formset, change)[source]

Given an inline formset save it to the database.

TransactionItemAdmin

class erp_framework.admin.admin.TransactionItemAdmin(parent_model, admin_site)[source]
formfield_for_dbfield(db_field, request, **kwargs)[source]

Hook for specifying the form Field instance for a given database Field instance.

If kwargs are given, they’re passed to the form Field’s constructor.

get_autocomplete_fields(request)[source]

See EntityAdmin.get_autocomplete_fields for fine-tuning options.

get_permission_override_model(request, **kwargs)[source]

Return a string reprsentation of the model to look into its permissions, :param request: :param kwargs: :return:

get_ra_permission_codename(action, model_name)[source]

Returns the codename of the permission for the specified action.

has_add_permission(request, obj=None)[source]

Return True if the given request has permission to add an object. Can be overridden by the user in subclasses.

has_change_permission(request, obj=None)[source]

Return True if the given request has permission to change the given Django model instance, the default implementation doesn’t examine the obj parameter.

Can be overridden by the user in subclasses. In such case it should return True if the given request has permission to change the obj model instance. If obj is None, this should return True if the given request has permission to change any object of the given type.

has_delete_permission(request, obj=None)[source]

Return True if the given request has permission to delete the given Django model instance, the default implementation doesn’t examine the obj parameter.

Can be overridden by the user in subclasses. In such case it should return True if the given request has permission to delete the obj model instance. If obj is None, this should return True if the given request has permission to delete any object of the given type.