This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/python/editor/editing-pdf-form-fields.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Editing PDF form fields | Nutrient Python SDK

Use form field editing to control validation and behavior in PDF workflows.

Common use cases include:

  • Setting fields to read-only after approval
  • Marking fields as required for validation
  • Reading default values for reset logic
  • Traversing parent-child field hierarchies
  • Accessing widgets for appearance updates
Download sample

How Nutrient helps

Nutrient Python SDK handles form field dictionaries, property updates, and hierarchy traversal.

The SDK handles:

  • PDF form field dictionaries and annotation structures
  • Recursive hierarchy traversal for parent-child fields
  • Flag manipulation at the byte level
  • Low-level widget access for appearance customization

Complete implementation

This example edits multiple form field properties in one pass:

from nutrient_sdk import Document
from nutrient_sdk import PdfEditor
from nutrient_sdk import PdfFormFieldType
from nutrient_sdk import NutrientException

Create the main function:

def main():

Opening a document with form fields

Open the PDF in a context manager(opens in a new tab) so resources are cleaned up after processing.

Then call form_field_collection to access:

  • Terminal fields (leaf fields with values)
  • Non-terminal fields (parent fields with children)
try:
with Document.open("input_forms.pdf") as document:
editor = PdfEditor.edit(document)
form_fields = editor.form_field_collection

Inspecting field properties

Iterate over fields to inspect key properties.

This sample reads:

  • Field name and full name
  • Field type
  • Terminal/parent state
  • Read-only and required flags
  • Current value and default value

Use this step for form auditing and validation setup.

for field in form_fields:
print(f"Name: {field.name}")
print(f"FullName: {field.full_name}")
print(f"FieldType: {field.field_type}")
print(f"IsTerminal: {field.is_terminal}")
print(f"IsReadOnly: {field.is_read_only}")
print(f"IsRequired: {field.is_required}")
print(f"Value: {field.value}")
print(f"DefaultValue: {field.default_value}")
print("---")

Making a field read-only

Find a field by full name and set it to read-only.

In this sample, Text1 is locked with is_read_only = True. If Text1 doesn’t exist in your input file, find_by_full_name() returns None and no update is applied.

text_field = form_fields.find_by_full_name("Text1")
if text_field is not None:
text_field.is_read_only = True

Making a field required

Find a field by full name and mark it as required.

In this sample, Check1 is marked required with is_required = True. If Check1 isn’t present in your input form, this lookup performs no operation.

check_field = form_fields.find_by_full_name("Check1")
if check_field is not None:
check_field.is_required = True

Reading a default value

Read a field’s default value for reset and change-tracking logic.

In this sample:

  • value returns the current value.
  • default_value returns the reset value.

If Dropdown1 isn’t present in your input form, the lookup returns None and the sample skips this read.

country_field = form_fields.find_by_full_name("Dropdown1")
if country_field is not None:
default_value = country_field.default_value
print(f"Default value: {default_value}")

Working with field hierarchy

Traverse field hierarchies by checking whether a field is terminal.

For non-terminal fields, use:

  • child_count to read child count.
  • get_child(i) to access each child.

Full names often use dot notation, for example Address.Street:

for field in form_fields:
if not field.is_terminal:
child_count = field.child_count
print(f"Parent field '{field.name}' has {child_count} children:")
for i in range(child_count):
child = field.get_child(i)
print(f" - Child: {child.name}")

Accessing widget annotations

Access widgets for terminal fields to inspect or update visual presentation.

In this sample:

  • widget_count returns the number of widgets.
  • get_widget(i) returns a widget by index.

A field can have one or more widgets across pages:

for field in form_fields:
if field.is_terminal:
widget_count = field.widget_count
print(f"Field '{field.name}' has {widget_count} widget(s)")
for i in range(widget_count):
widget = field.get_widget(i)
# Access widget properties for appearance customization

Batch updating field properties

Apply updates to multiple fields using type-based conditions.

In this sample:

  • Text fields are marked required.
  • Signature fields are set to read-only.

Use this pattern for workflow-driven form rules:

Compare field_type directly against enum members (for example, PdfFormFieldType.TEXT and PdfFormFieldType.SIGNATURE).

for field in form_fields:
if field.is_terminal:
# Make all text fields required
if field.field_type == PdfFormFieldType.TEXT:
field.is_required = True
# Make all signature fields read-only until other fields are filled
if field.field_type == PdfFormFieldType.SIGNATURE:
field.is_read_only = True

Saving the modified form

Save the output PDF and close the editor:

editor.save_as("output.pdf")
editor.close()
except NutrientException as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()

Conclusion

Use this workflow to edit form field properties:

  1. Open the document using a context manager(opens in a new tab) for automatic resource cleanup.
  2. Create an editor and access the form field collection with form_field_collection.
  3. The form field collection provides iteration and lookup operations for all fields in the document.
  4. Inspect field properties using property access: name, full_name, field_type, is_terminal, is_read_only, is_required, value, and default_value.
  5. Fully qualified names use dot-notation for hierarchical fields (e.g. "Address.Street").
  6. Set fields to read-only with find_by_full_name() and is_read_only = True to lock fields after workflow milestones.
  7. Mark fields as required with is_required = True to enforce validation, preventing form submission until values are provided.
  8. Read default values with default_value for reset operations and change detection.
  9. Navigate field hierarchy with is_terminal, child_count, and get_child(i) for parent-child relationships.
  10. Access widget annotations with widget_count and get_widget(i) for appearance customization.
  11. Batch update properties by iterating terminal fields and applying conditional logic based on field_type comparisons.
  12. Save the document with save_as() to persist all property modifications.

Sample field names such as Text1, Check1, and Dropdown1 are illustrative. If those names don’t exist in your input PDF, those targeted operations are safely skipped.

For related form workflows, refer to the Python SDK editor guides.