Field Types

When you add a field — on a new DocType or an existing form — the Type you choose decides five things at once:

  • how the value is stored in the database,
  • what the user sees and how they enter it,
  • what validation happens automatically,
  • how the field behaves in filters, list views and reports,
  • what the API returns for it.

Getting it right the first time matters, because changing a field's type after it holds data is risky — see Changing a type later.

This page covers every type GarmentFlow itself uses, with a real example of each.

Choosing quickly

You want to store Use
A short name, code or reference Data
A paragraph of notes Small Text
Formatted text with headings and bold Text Editor
A whole number Int
A measurement Float
Money Currency
A proportion Percent
Yes or no Check
One of a fixed list you define Select
One record from another table Link
Several rows of detail Table
A date Date
A file or photo Attach / Attach Image
A star score Rating
Nothing — it is layout Section Break, Column Break, Tab Break

The rest of this page explains each one.

The Options field

Most types need nothing but a label. Some need a second piece of information, and it always goes in the same place: the Options field on the field's row.

What Options means depends on the type, which is the single most confusing thing about Frappe fields:

Type Options holds
Link The DocType to link to — Production Unit
Table, Table MultiSelect The child DocType — Production Order Operation
Select, MultiSelect The choices, one per line
Dynamic Link The fieldname that holds the DocType name
Currency The fieldname holding the currency, or a currency code
Image The fieldname holding the image URL
Rating The number of stars — 5
Code The language — JSON, Python, JavaScript
Data Optionally a format: Email, Phone, URL

Everything else leaves it blank.


Text

Data

Stores up to 140 characters of plain text. The default choice for anything short.

Use for names, codes, references, batch numbers, roll numbers.

Example in GarmentFlow: Tech Pack.model_name, Work Center.station_name.

Put a format in Options and Frappe validates and renders it accordingly:

Options Effect
Email Must be a valid address; renders as a mailto link
Phone Renders as a dial link
URL Renders as a clickable link

Example: Catalog Settings.custom_quote_email is a Data field with Options Email.

Don't use Data for a paragraph. It truncates at 140 characters without warning.

Small Text

Stores plain text of any length, shown as a box a few lines tall.

Use for notes, reasons, short descriptions — anything a person types in sentences but that needs no formatting.

Example: Work Center.notes, Published Tech Pack.short_description.

This is the right default for "notes" fields. Reach for it before Text Editor.

Text and Long Text

Text and Long Text also store unformatted text; Long Text is for genuinely large content.

Use Long Text when you are storing something machine-generated and big — a serialized plan, an imported blob.

Example: Production Order.batch_plan_json.

Text Editor

Stores HTML. Gives the user a rich editor: bold, lists, headings, tables, images.

Use where formatting is part of the meaning — instructions to a customer, marketing copy.

Example: Tech Pack.general_comments, Published Tech Pack.marketing_description.

Two costs: the stored value is HTML, so it is awkward to filter or compare, and pasted content from Word brings styling with it. Use Small Text unless someone genuinely needs formatting.

Code

Stores plain text, displayed in a monospaced editor with syntax highlighting. Options sets the language.

Use for configuration a technical user edits.

Example: Asset Label Template.design, a Code field with Options JSON.

JSON

Stores structured data as JSON, with a JSON-aware editor.

Use when the shape genuinely varies and a child table would be wrong — a per-size quantity map, coordinates, a saved layout.

Example: Catalog Cart.items_json, Pattern POM.coordinates, Sample.size_chart_json.

Caution

A JSON field cannot be filtered, sorted or reported on usefully. If you find yourself wanting to report across what is inside it, you wanted a child table.


Numbers

Int

Stores a whole number. No decimals.

Use for counts of things that cannot be fractional: pieces, plies, operators, boxes.

Example: Work Center.max_ply, Production Order.units_per_box.

Float

Stores a decimal number, rounded to the site's float precision (2 by default).

Use for measurements: lengths, weights, hours, minutes.

Example: Work Center.max_table_length, Batch Operation Step.expected_duration_days.

Important

If a Float is calculated on a submitted document, round it to the field's precision in both your client and server code. A value that differs in the tenth decimal place triggers "Not allowed to change after submission".

Currency

Stores money. Formatted with a currency symbol and the right number of decimals.

Options should name the field holding the currency, so a multi-currency document formats each amount correctly. Leave it blank to use the company default.

Example: Work Center.hour_rate, Batch Operation Step.actual_cost, Published Tech Pack.base_price (with Options currency).

Always use Currency rather than Float for money — it formats correctly, rounds to currency precision, and totals properly in reports.

Percent

Stores a number displayed with a % sign. Stored as the number itself: 85 means 85%, not 0.85.

Use for efficiency, tolerance, shrinkage, variance.

Example: Work Center.efficiency_percent, Work Center.max_lay_overflow_pct.

Rating

Stores a score, shown as clickable stars. Options sets how many stars.

Example: QC Inspection.quality_rating with Options 5; Interview Skill Test.star_rating.

Good for a human judgement. Bad for anything that should be calculated — use Float or Percent for those.


Dates and time

Date

Stores a calendar date, shown in the user's date format.

Example: Production Order.end_date, Cutting Order.date.

Set Default to Today for a field that usually means "now".

Datetime

Stores a date and a time, in the site's time zone.

Use when the time of day matters: when a breakdown was reported, when a box was closed.

Example: Production Order.completed_on, Packing Box.packed_at.

Time

Stores a time of day with no date. Rare — usually you want Datetime.


Choices

Check

Stores 1 or 0, shown as a tick box.

Example: Work Center.is_default, Published Tech Pack.published.

In filters and scripts it is a number, not true/false: doc.published == 1. Name it as a positive statement (is_active, not is_not_active) — a negative tick box is read wrongly by everyone.

Select

Stores one value from a list you define. Options holds the choices, one per line.

Pending
In Progress
Done

Example: Batch Operation Step.status, Work Center.status, Production Order.pack_rule.

Leave the first line blank if the field should be able to have no value.

Use Select when the list is short, fixed, and owned by you. When the list is long, or users need to add to it, create a small DocType and use a Link instead — that way they can manage it without a System Manager.

Caution

Changing a Select's options does not change data already saved. Rename In Progress to Running and every existing record still says In Progress, silently failing filters. Add new options freely; renaming needs a data migration.

MultiSelect

Stores several values from a list, comma-separated. Options as for Select.

Example: QC Alert Configuration.alert_method — Email, System Notification, SMS.

Fine for a handful of flags. For anything you need to report on, use a Table MultiSelect.


This is where Frappe's data model lives, and where most design decisions are made.

Stores the name of a record in another DocType. Options is that DocType.

The user gets a searchable dropdown; the value renders as a clickable link; the framework blocks deleting the target while something points at it.

Example: Production Order.tech_pack → Tech Pack. Work Center.production_unit → Production Unit.

Three things you can do with a Link that are worth knowing:

Pull values from it without a script. Add another field and set its Fetch From to link_fieldname.target_fieldname — see Extending forms.

Restrict what it offers. A client script with frm.set_query() can filter the dropdown to, say, internal units only.

Report through it. In the Report view you can add columns from the linked record.

Stores the name of a record in a DocType named by another field. Options is the fieldname holding the DocType name.

You always need a pair: one Link (or Select) field holding the DocType, and the Dynamic Link holding the record.

Example: Operation Ledger Entry.reference_doctype holds Cutting Order, and reference_name is a Dynamic Link with Options reference_doctype.

Also Production Order.source_doctype / source_name, and Subcontract Cost Allocation.reference_doctype / reference_name.

Use it when a record can point at several different kinds of thing. Don't use it when there is only one possible target — a plain Link is simpler, safer and faster.

Table

Stores child rows. Options is the child DocType.

Use whenever one record needs many of something: operations on an order, sizes on a marker, rows on an invoice.

Example: Production Order.operation_plan → Production Order Operation. Production Unit.operations → Production Unit Operation.

Three practical notes:

  • The child DocType must have Is Child Table ticked.
  • The grid shows only the child fields with In List View ticked. Tick two or three; the rest appear when a row is expanded.
  • The list API does not return child tables. Fetch the single document to get them — see API & integrations.

Row order is the idx column, in the order shown. If order carries meaning — as it does on a Production Order's operation plan — that is where it lives.

Table MultiSelect

Stores several links, shown as removable chips instead of a grid. Options is a child DocType containing a single Link field.

Example: Fabric.technologies → Fabric Technology Item. QC Defect Category.operations → QC Defect Category Operation. Published Tech Pack.terms_and_conditions → Published Tech Pack Terms.

Use it for "which of these apply" — tags, applicable operations, certifications. It reports properly (unlike MultiSelect) because each value is a real row.


Files, media and specials

Attach

Stores the URL of an uploaded file.

Example: a scanned certificate, a supplier's spec sheet.

Attach Image

Like Attach, restricted to images and shown as a thumbnail.

Example: Published Tech Pack.hero_image, Brand logos.

Set Form Settings → Image Field in Customize Form to make one of these the record's picture in lists and link previews.

Image

Displays an image whose URL is in another field. Options is that fieldname. It stores nothing itself.

Example: Fabric Washcare.image with Options image_url.

Use it to show a picture that arrives from somewhere else. To let a user upload one, use Attach Image.

Signature

Stores a drawn signature as an image. Renders as a pad the user signs with a finger or mouse.

Example: Operation Ledger Entry.accepted_signature — a handover signed on the floor.

Color

Stores a colour, with a picker.

Example: Work Center Type.color, Variant.color, QC Defect Category.color_code.

Useful when the value drives something visual — the tiles on the floor monitor are coloured from a Work Center Type's colour.

Barcode

Stores a code and renders the barcode image.

Example: Tech Registry.barcode.

Geolocation

Stores coordinates or a drawn area, with a map.

Example: Production Unit.location, QC Inspection.geolocation.


Layout

These hold no data. They exist to make the form readable, and they are worth as much attention as the fields themselves.

Type Effect
Section Break Starts a new block. Give it a Label for a heading, or leave it blank for a plain divider
Column Break Splits the current section into another column
Tab Break Starts a new tab
Heading A heading inside a section
HTML Renders fixed HTML, or a placeholder a script fills in
Button A button that triggers a client script

Example: Tech Pack uses Tab Breaks for Dashboard, Design, Registry, Logistics and Costs; Heading fields inside them; and HTML fields such as Production Order.cutting_summary, where the entire Cut Plan interface is rendered by a script into an empty HTML field.

Two layout habits worth copying:

  • Collapse a Section Break you rarely need (there is a Collapsible option), so the form opens short.
  • Three fields per section, two columns reads far better than twelve fields in a row.

Other types you may see

The Type dropdown lists more than the above. The ones you are most likely to meet:

Type For
Read Only Displays a value the user cannot edit and no script sets — usually fetched
Password Stored encrypted, never displayed
Duration A length of time, entered as days/hours/minutes
Autocomplete Free text with suggestions
Markdown Editor Markdown rather than HTML
HTML Editor Raw HTML with syntax highlighting
Fold Hides everything after it behind a "show more"
Icon Picks an icon from the standard set

If you meet one that isn't here, the safe move is to look at how a standard DocType uses it before adopting it.


Changing a type later

Sometimes safe, sometimes not.

Change Risk
Data → Small Text, Small Text → Text Safe. Wider storage
Int → Float Safe
Float → Int Loses decimals, permanently
Data → Link Works only if every existing value is an exact record name
Link → Data Safe, but you lose validation and the click-through
Select → Link Needs a DocType with matching records
Anything → Table Not a conversion. Add a new field

Before changing a type on a field that holds data:

  1. Back up, or do it on a test site first.
  2. Export the current values so you can compare afterwards.
  3. Change it, then check a sample of real records.
  4. Check anything that reads the field: reports, print formats, scripts, integrations.

If in doubt, add a new field with the right type, migrate the values, and hide the old one. It is slower and it cannot go wrong.

How the type shows up elsewhere

Type In the API In filters In reports
Data, Select, Link String All operators Text column
Int, Float, Currency, Percent Number Numeric comparisons Totals
Check 1 / 0 = 1 Count
Date, Datetime ISO string — "2026-08-20" Ranges, between Date grouping
Table Only on the single-document fetch Not filterable directly Needs a join
JSON, Text Editor String Not usefully Not usefully

That last row is the practical reason to prefer structured types: anything you might want to filter, total or report on should be its own typed field, not buried in JSON or rich text.

What to do next

Back to Creating DocTypes to build a record type, or Extending forms to add fields to a form GarmentFlow already has.

WhatsApp