Skip to content

[chores:fix] Preserved text -> jsonb migration for JSONField fields #297#299

Merged
nemesifier merged 2 commits into
masterfrom
fix-jsonfield-migrations
May 21, 2026
Merged

[chores:fix] Preserved text -> jsonb migration for JSONField fields #297#299
nemesifier merged 2 commits into
masterfrom
fix-jsonfield-migrations

Conversation

@nemesifier

Copy link
Copy Markdown
Member

Historical migrations were updated to use models.TextField instead of jsonfield.fields.JSONField for fields originally backed by the third-party jsonfield library.

The original jsonfield.fields.JSONField inherited from TextField and stored values as PostgreSQL text. Preserving the historical field semantics as TextField (rather than models.JSONField) allows Django to correctly detect the transition from text -> jsonb and generate the required ALTER COLUMN ... TYPE jsonb migration SQL during upgrades.

The jsonfield package was also dropped from requirements.txt since no code or migration references it anymore.

Closes #297

@nemesifier nemesifier self-assigned this May 20, 2026
@nemesifier nemesifier added the bug label May 20, 2026
@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8ceec033-a12b-4f3a-9a1b-671b28781356

📥 Commits

Reviewing files that changed from the base of the PR and between e0896c0 and b756565.

📒 Files selected for processing (5)
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{sh,bash,py,js,ts,tsx,jsx,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/__init__.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb,sh}

📄 CodeRabbit inference engine (Custom checks)

Avoid unnecessary comments or docstrings for code that is already clear

Files:

  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/__init__.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}: Code formatting must be compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Variables, functions, classes, and files must have descriptive and consistent names
Errors that cannot be resolved by the user must be logged with error level
Unusual conditions must be logged with warning level
Important background actions must be logged with info level

Files:

  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/__init__.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
**/*.{py,html,txt}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests: Ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/__init__.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
**/*.{js,ts,tsx,jsx,py,java,cs}

📄 CodeRabbit inference engine (Custom checks)

Provide user-facing messages for errors that the user can solve autonomously (for example, validation errors)

Files:

  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/__init__.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
🔇 Additional comments (5)
openwisp_network_topology/migrations/0007_create_new_address_field.py (1)

16-16: LGTM!

openwisp_network_topology/migrations/0010_properties_json.py (1)

21-21: LGTM!

openwisp_network_topology/migrations/__init__.py (1)

35-41: LGTM!

tests/openwisp2/sample_network_topology/migrations/0001_initial.py (1)

239-239: LGTM!

tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py (1)

21-21: LGTM!


📝 Walkthrough

Walkthrough

This pull request removes the jsonfield dependency and converts all historical migration fields that used jsonfield.fields.JSONField to django.db.models.TextField across production and test migrations. It also updates migration helper functions to import json and serialize/deserialize node.addresses as JSON strings, and removes jsonfield from requirements.txt. Field attributes like blank and default are preserved where applicable.

Sequence Diagram(s)

sequenceDiagram
  participant ComponentA
  participant ComponentB
  ComponentA->>ComponentB: observable interaction
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Possibly related issues

  • #297: [bug] Missing PostgreSQL text -> jsonb migration for JSONField replacement — the linked issue discusses preserving historical TextField-backed migrations to allow Django to generate correct ALTER COLUMN TYPE jsonb SQL; this PR follows the approach of keeping TextField storage in historical migrations.

Suggested labels

dependencies

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title includes required type prefix [chores:fix], is descriptive, and references the issue #297 being addressed.
Description check ✅ Passed PR description clearly explains the changes, why they matter, and includes the issue reference; checklist and screenshots are not applicable to this technical change.
Linked Issues check ✅ Passed All code changes directly address issue #297 by preserving TextField semantics in migrations so Django detects text->jsonb transitions and generates required ALTER COLUMN TYPE jsonb SQL.
Out of Scope Changes check ✅ Passed All changes are scoped to addressing the jsonfield migration issue; updates to migration files, requirements.txt removal, and helper function updates are all directly related to preserving text->jsonb migration semantics.
Bug Fixes ✅ Passed Fixes bug: converts historical migrations to TextField enabling text→jsonb detection. Root cause fixed. Data migrations use json.dumps(). Existing tests validate JSON field behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-jsonfield-migrations

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the dependencies Pull requests that update a dependency file label May 20, 2026
@kilo-code-bot

kilo-code-bot Bot commented May 20, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

The incremental changes correctly address edge cases identified in the previous review.

Summary of Changes Since Previous Review

  1. Fixed empty addresses handling in migrate_openvpn_ids_0012 (migrations/__init__.py, lines 35-38): Added a check for empty addresses list before attempting to index into it, preventing an IndexError when addresses is empty.
  2. Fixed mutable default arguments (5 migration files): Changed default=[] to default=list to follow Django best practices and avoid shared mutable defaults.

Files Reviewed in This Incremental Review (5 files)

  • openwisp_network_topology/migrations/__init__.py - Added empty list check for addresses
  • openwisp_network_topology/migrations/0007_create_new_address_field.py - Fixed mutable default
  • openwisp_network_topology/migrations/0010_properties_json.py - Fixed mutable default
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py - Fixed mutable default
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py - Fixed mutable default

Reviewed by kimi-k2.5-0127 · 88,723 tokens

@coveralls

coveralls commented May 20, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 98.873%. first build — fix-jsonfield-migrations into master

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openwisp_network_topology/migrations/0010_properties_json.py`:
- Around line 13-16: Migration 0010 changed node.addresses to a TextField
defaulting to dict which can leave stored values as stringified lists; update
migrate_openvpn_ids_0012 in migration 0012_update_openvpn_netjson_ids.py so it
first detects when node.addresses is a str and deserializes it (e.g., json.loads
or ast.literal_eval) into a Python list before doing node.addresses[0] =
node.label, ensuring you handle non-list/None cases safely and then save the
instance; alternatively, if you prefer, revert 0010 to store JSON-compatible
types, but the minimal fix is to add the deserialization and validation in
migrate_openvpn_ids_0012.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5d9d6137-49fc-4294-a587-3c3159223cf3

📥 Commits

Reviewing files that changed from the base of the PR and between c68ad25 and 2cf7242.

📒 Files selected for processing (8)
  • openwisp_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • requirements.txt
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
💤 Files with no reviewable changes (1)
  • requirements.txt
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.13 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{sh,bash,py,js,ts,tsx,jsx,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb,sh}

📄 CodeRabbit inference engine (Custom checks)

Avoid unnecessary comments or docstrings for code that is already clear

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}: Code formatting must be compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Variables, functions, classes, and files must have descriptive and consistent names
Errors that cannot be resolved by the user must be logged with error level
Unusual conditions must be logged with warning level
Important background actions must be logged with info level

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{py,html,txt}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests: Ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs}

📄 CodeRabbit inference engine (Custom checks)

Provide user-facing messages for errors that the user can solve autonomously (for example, validation errors)

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • openwisp_network_topology/migrations/0001_initial.py

Comment thread openwisp_network_topology/migrations/0010_properties_json.py


Historical migrations were updated to use models.TextField instead of
jsonfield.fields.JSONField for fields originally backed by the
third-party jsonfield library.

The original jsonfield.fields.JSONField inherited from TextField and
stored values as PostgreSQL text. Preserving the historical field
semantics as TextField (rather than models.JSONField) allows Django to
correctly detect the transition from text -> jsonb and generate the
required ALTER COLUMN ... TYPE jsonb migration SQL during upgrades.

The jsonfield package was also dropped from requirements.txt since no
code or migration references it anymore.

Closes #297
@nemesifier nemesifier force-pushed the fix-jsonfield-migrations branch from 2cf7242 to e0896c0 Compare May 20, 2026 23:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openwisp_network_topology/migrations/__init__.py`:
- Around line 29-38: The migration assumes addresses (node.addresses) decodes to
a non-empty list and does addresses[0] = node.label, which will IndexError on an
empty list; update the logic after json.loads() to ensure addresses is a list
and has at least one element (e.g., if not addresses: append node.label or
insert at index 0) before assigning, then continue to json.dumps into
node.addresses and save; touch the block around json.loads, the addresses[0] =
node.label assignment, and node.addresses = json.dumps(addresses).

In `@openwisp_network_topology/migrations/0007_create_new_address_field.py`:
- Line 16: Change the mutable default list literal to a callable: replace the
TextField default in the migration that defines models.TextField(default=[])
(migration 0007_create_new_address_field) to use default=list instead; this
keeps semantics consistent with other defaults (e.g., default=dict) and is safe
since migration 0008's migrate_addresses populates the field.

In `@openwisp_network_topology/migrations/0010_properties_json.py`:
- Line 21: The TextField in the migration currently uses a mutable default
(default=[]) which can cause shared-state bugs; update the field declaration in
the migration (the line with models.TextField(blank=True, default=[])) to use a
callable default instead (default=list) so each instance gets its own empty list
object while preserving blank=True and existing behavior.

In `@tests/openwisp2/sample_network_topology/migrations/0001_initial.py`:
- Line 239: The migration defines the "addresses" field as
models.TextField(default=[]) which uses a mutable default; change it to use a
callable default by replacing default=[] with default=list on the
models.TextField for the "addresses" field (i.e., update the tuple ("addresses",
models.TextField(default=[])) to use models.TextField(default=list)) so tests
mirror production migrations and avoid shared mutable defaults.

In `@tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py`:
- Line 21: The migration uses a mutable default (models.TextField(blank=True,
default=[])); change the field's default to the callable list by replacing
default=[] with default=list to avoid sharing mutable defaults; update the
models.TextField declaration in the migration (the field definition in
0002_json_properties.py) to use default=list so it matches the production
migration and is safe for Django migrations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4fbca7a2-4654-445a-99fa-d5db633c9f15

📥 Commits

Reviewing files that changed from the base of the PR and between 2cf7242 and e0896c0.

📒 Files selected for processing (9)
  • openwisp_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • requirements.txt
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
💤 Files with no reviewable changes (1)
  • requirements.txt
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=4.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Kilo Code Review
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{sh,bash,py,js,ts,tsx,jsx,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

Cryptic or non-obvious code (regex, complex bash commands, or hard-to-read code) must include a concise comment explaining why it is needed and why the complexity is acceptable

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb,sh}

📄 CodeRabbit inference engine (Custom checks)

Avoid unnecessary comments or docstrings for code that is already clear

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}

📄 CodeRabbit inference engine (Custom checks)

**/*.{js,ts,tsx,jsx,py,java,cs,cpp,c,go,rb}: Code formatting must be compact and readable. Do not add excessive blank lines, especially inside function or method bodies
Variables, functions, classes, and files must have descriptive and consistent names
Errors that cannot be resolved by the user must be logged with error level
Unusual conditions must be logged with warning level
Important background actions must be logged with info level

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{py,html,txt}

📄 CodeRabbit inference engine (Custom checks)

For Django pull requests: Ensure all user-facing strings are marked as translatable using the Django i18n framework

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0001_initial.py
**/*.{js,ts,tsx,jsx,py,java,cs}

📄 CodeRabbit inference engine (Custom checks)

Provide user-facing messages for errors that the user can solve autonomously (for example, validation errors)

Files:

  • openwisp_network_topology/migrations/0007_create_new_address_field.py
  • openwisp_network_topology/migrations/0010_properties_json.py
  • tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py
  • tests/openwisp2/sample_network_topology/migrations/0001_initial.py
  • openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/__init__.py
  • tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py
  • openwisp_network_topology/migrations/0001_initial.py
🔇 Additional comments (7)
openwisp_network_topology/migrations/0001_initial.py (1)

67-71: LGTM!

Also applies to: 115-119

openwisp_network_topology/migrations/0010_properties_json.py (1)

13-16: LGTM!

Also applies to: 26-29

openwisp_network_topology/migrations/0013_add_user_defined_properties_field.py (1)

13-18: LGTM!

Also applies to: 23-28

openwisp_network_topology/migrations/__init__.py (1)

2-3: LGTM!

Also applies to: 21-22

tests/openwisp2/sample_network_topology/migrations/0001_initial.py (1)

242-246: LGTM!

Also applies to: 310-314

tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py (1)

13-16: LGTM!

Also applies to: 26-29

tests/openwisp2/sample_network_topology/migrations/0003_add_user_defined_properties_field.py (1)

13-18: LGTM!

Also applies to: 23-28

Comment thread openwisp_network_topology/migrations/__init__.py
Comment thread openwisp_network_topology/migrations/0007_create_new_address_field.py Outdated
Comment thread openwisp_network_topology/migrations/0010_properties_json.py Outdated
Comment thread tests/openwisp2/sample_network_topology/migrations/0001_initial.py Outdated
Comment thread tests/openwisp2/sample_network_topology/migrations/0002_json_properties.py Outdated
- Replaced default=[] with default=list in migrations for consistency
  with default=dict already used in the same files and to avoid the
  mutable-literal-as-default anti-pattern.
- Guarded migrate_openvpn_ids_0012 against an empty addresses list so
  it falls back to [node.label] instead of raising IndexError.

Related to #299
@nemesifier nemesifier merged commit b756565 into master May 21, 2026
18 checks passed
@nemesifier nemesifier deleted the fix-jsonfield-migrations branch May 21, 2026 16:03

@pandafy pandafy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nemesifier does the change to models.JSONField handle this?

The second problem is more subtle and it only shows up on PostgreSQL, which is what most production deployments use. In openwisp_network_topology/admin.py the NodeAdmin declares search_fields = ["addresses", "label", "properties"], and the device integration in openwisp_network_topology/integrations/device/overrides.py adds source__addresses and target__addresses to a similar list. With the old third party JSONField these columns were stored as plain text, so the icontains lookup that the admin search uses under the hood translated to a normal ILIKE and worked fine. With the built in JSONField the column type becomes jsonb on PostgreSQL, and PostgreSQL does not define an ILIKE operator for jsonb, so as soon as someone uses the admin search box on the Node list view they will get an error along the lines of operator does not exist: jsonb ~~* unknown. Our test suite runs on SpatiaLite where the column is still text under the hood, so the regression will not be caught by CI. We need to either drop the JSON columns from the search fields or cast them to text in the search. The same review should be done on the parallel controller and radius PRs.

Quoted from #259 (review)

@nemesifier

Copy link
Copy Markdown
Member Author

@nemesifier does the change to models.JSONField handle this?

The second problem is more subtle and it only shows up on PostgreSQL, which is what most production deployments use. In openwisp_network_topology/admin.py the NodeAdmin declares search_fields = ["addresses", "label", "properties"], and the device integration in openwisp_network_topology/integrations/device/overrides.py adds source__addresses and target__addresses to a similar list. With the old third party JSONField these columns were stored as plain text, so the icontains lookup that the admin search uses under the hood translated to a normal ILIKE and worked fine. With the built in JSONField the column type becomes jsonb on PostgreSQL, and PostgreSQL does not define an ILIKE operator for jsonb, so as soon as someone uses the admin search box on the Node list view they will get an error along the lines of operator does not exist: jsonb ~~* unknown. Our test suite runs on SpatiaLite where the column is still text under the hood, so the regression will not be caught by CI. We need to either drop the JSON columns from the search fields or cast them to text in the search. The same review should be done on the parallel controller and radius PRs.

Quoted from #259 (review)

I double checked on a prod instance and the search_fields functionality works fine, thanks for checking!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Missing PostgreSQL text -> jsonb migration for JSONField replacement

3 participants