Model Field Conventions
Developer guide for the Enezaframework. Part of the Developer documentation.
Table of Contents
- Overview
- The Three Rules
- Correct and Incorrect Examples
- Model-Level Image Size Definition
- Configuration Keys
- Change History
- Related Guides
Overview
Every model in this project follows three mandatory field conventions. They exist so migrations, diffs, and reviews stay readable and predictable. Apply them to every field you write, including the samples you copy from other guides.
There is no diagram in this guide; the rules and tables are the whole content.
The Three Rules
- One field per line. Never declare two or more fields on the same line.
- Always set
verbose_name. Every field must include averbose_namekeyword argument. - Multi-line fields close
)on its own line. When a field declaration spans multiple lines (for example aForeignKeywithrelated_name,on_delete, orhelp_text), the closing parenthesis goes on its own line, aligned with the start of the field declaration.
Correct and Incorrect Examples
Correct
class VendorTable(EnezaMaster):
vendorno = models.CharField(
max_length=50,
unique=True,
verbose_name="Vendor No.",
)
searchname = models.CharField(
max_length=255,
verbose_name="Search Name",
)
vendorgroup = models.ForeignKey(
"VendorGroup",
on_delete=models.PROTECT,
related_name="vendors",
verbose_name="Vendor Group",
)
Incorrect
class VendorTable(EnezaMaster):
# Two fields on one line:
vendorno = models.CharField(max_length=50); searchname = models.CharField(max_length=255)
# Missing verbose_name:
blocked = models.BooleanField(default=False)
# Closing parenthesis not on its own aligned line:
vendorgroup = models.ForeignKey("VendorGroup", on_delete=models.PROTECT,
verbose_name="Vendor Group")
The first block is the one used across this documentation series.
Model-Level Image Size Definition
Enezaframework lets you define image display sizes directly in the model field definition. A single generic template can then serve many models with different image requirements, because the widget reads the size configuration off the bound field.
flowchart TD
MODEL[Model field:<br/>ConfigurableImageField<br/>image_size_config] --> FORMFIELD[formfield exposes<br/>image_size_config]
FORMFIELD --> TAG[Template tag:<br/>is_image_field / smart_field]
TAG --> WIDGET[image_upload_widget]
WIDGET --> PREVIEW[Preview + responsive sizing]
WIDGET --> CLIENT[Client-side validation:<br/>type + size]Import ConfigurableImageField from enezaframework.models and pass image_size_config.
from django.db import models
from enezaframework.models import ConfigurableImageField
class Profile(models.Model):
avatar = ConfigurableImageField(
upload_to="profile_images/",
image_size_config={
"max_height": 200,
"max_width": 200,
"mobile_max_height": 150,
"mobile_max_width": 150,
},
verbose_name="Avatar",
)
banner = ConfigurableImageField(
upload_to="banner_images/",
image_size_config={
"max_height": 300,
"max_width": 800,
"mobile_max_height": 200,
"mobile_max_width": 600,
},
verbose_name="Banner",
)
ConfigurableImageField subclasses models.ImageField, so all normal ImageField options
(upload_to, blank, null, verbose_name, and so on) still apply.
Multiple images
For a field that stores several images, use ConfigurableMultipleImageField. It subclasses
models.JSONField and stores a list of image paths.
from enezaframework.models import ConfigurableMultipleImageField
class Listing(models.Model):
photos = ConfigurableMultipleImageField(
upload_to="listing_photos/",
max_images=5,
image_size_config={
"max_height": 400,
"max_width": 400,
"mobile_max_height": 250,
"mobile_max_width": 250,
},
verbose_name="Photos",
)
max_imagesdefaults to5and may not exceed20.- The default value is an empty list.
Configuration Keys
image_size_config accepts these keys:
| Key | Type | Description |
|---|---|---|
max_height |
int | Maximum display height in pixels (desktop). |
max_width |
int | Maximum display width in pixels (desktop). |
mobile_max_height |
int | Maximum display height on mobile. |
mobile_max_width |
int | Maximum display width on mobile. |
The configuration is validated when the model class is created:
- Only the keys above are allowed.
- Every value must be a positive integer.
- Values above
10000pixels are rejected. mobile_max_heightmust not exceedmax_height, andmobile_max_widthmust not exceedmax_width.
The field exposes helpers:
field = Profile._meta.get_field("avatar")
field.has_size_config() # bool
field.get_size_config() # copy of the config dict
For ConfigurableMultipleImageField, max_images must be a positive integer no greater than 20.
Client-side, the widget validates file type (JPG, PNG, GIF) and file size (2 MB limit) before upload;
server-side validation still applies through the underlying ImageField/form field.
Template integration uses the form_extras tags; the simplest is
{% smart_field form "avatar" %}. See
Frontend Templates & UI Reuse.
Change History
Dated changes that affect this guide, taken from
docs/Release note/CHANGELOG.md and the release notes. For the
complete history, see the changelog.
| Date | Version | What changed |
|---|---|---|
| 2026-06-30 | 0.2.8 | Field configuration expanded with full_width, column width: "full", display: "label", rich text, and button-group widgets. |
The three mandatory field conventions above are long-standing project rules and are not tied to a
changelog entry. The model-level image size fields (ConfigurableImageField,
ConfigurableMultipleImageField) also have no dated changelog entry in the 0.2.7–0.2.19 window.