---
title: "Editing PDF form fields | Nutrient Python SDK"
canonical_url: "https://www.nutrient.io/guides/python/editor/editing-pdf-form-fields/"
md_url: "https://www.nutrient.io/guides/python/editor/editing-pdf-form-fields.md"
last_updated: "2026-06-09T10:32:42.848Z"
description: "How to edit PDF form fields using Nutrient Python SDK."
---

# Editing PDF form fields

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](https://www.nutrient.io/downloads/samples/python/editing-pdf-form-fields.zip)

## 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:

```python

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

```

Create the main function:

```python

def main():

```

## Opening a document with form fields

Open the PDF in a [context manager](https://docs.python.org/3/reference/datamodel.html#context-managers) 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)

```python

    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.

```python

            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.

```python

            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.

```python

            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.

```python

            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`:

```python

            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:

```python

            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`).

```python

            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:

```python

            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](https://docs.python.org/3/reference/datamodel.html#context-managers) 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](https://www.nutrient.io/guides/python/editor.md).
---

## Related pages

- [Adding a custom page to a PDF document](/guides/python/editor/add-custom-page-to-pdf.md)
- [Adding annotations to a PDF document](/guides/python/editor/add-annotations-to-pdf.md)
- [Adding invisible digital signatures to a PDF document](/guides/python/editor/add-invisible-signature-to-pdf.md)
- [Adding interactive form fields to a PDF document](/guides/python/editor/add-form-fields-to-pdf.md)
- [Adding free text annotations to a PDF document](/guides/python/editor/add-freetext-annotations-to-pdf.md)
- [Adding link annotations to a PDF document](/guides/python/editor/add-link-annotations-to-pdf.md)
- [Adding redaction annotations to a PDF document](/guides/python/editor/add-redaction-annotations-to-pdf.md)
- [Adding shape annotations to a PDF document](/guides/python/editor/add-shape-annotations-to-pdf.md)
- [Adding stamp annotations to a PDF document](/guides/python/editor/add-stamp-annotations-to-pdf.md)
- [Adding sticky note annotations to a PDF document](/guides/python/editor/add-sticky-note-annotations-to-pdf.md)
- [Adding text markup annotations to a PDF document](/guides/python/editor/add-text-markup-annotations-to-pdf.md)
- [Advanced digital signature workflows](/guides/python/editor/advanced-digital-signatures.md)
- [Adding visible digital signatures to a PDF document](/guides/python/editor/add-visible-signature-to-pdf.md)
- [Detecting and adding form fields to a PDF document](/guides/python/editor/detect-and-add-form-fields.md)
- [Editing PDF metadata with Nutrient Python SDK](/guides/python/editor/editing-pdf-metadata.md)
- [Managing PDF page order](/guides/python/editor/manage-pdf-page-order.md)
- [Merging PDFs](/guides/python/editor/merge-pdf-into-other-pdf.md)
- [Nutrient Python SDK editor guides](/guides/python/editor.md)
- [Filling PDF form fields](/guides/python/editor/fill-pdf-form.md)

