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_emailis a Data field with Options
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 OptionsJSON.
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.
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.
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 Optionscurrency).
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_ratingwith Options5;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.
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.
Links to other records
This is where Frappe's data model lives, and where most design decisions are made.
Link
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.
Dynamic Link
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_doctypeholdsCutting Order, andreference_nameis a Dynamic Link with Optionsreference_doctype.Also
Production Order.source_doctype/source_name, andSubcontract 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,Brandlogos.
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.imagewith Optionsimage_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 Packuses Tab Breaks for Dashboard, Design, Registry, Logistics and Costs; Heading fields inside them; and HTML fields such asProduction 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:
- Back up, or do it on a test site first.
- Export the current values so you can compare afterwards.
- Change it, then check a sample of real records.
- 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.