Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use objects with only additionalProperties (no pre-defined fields) within schema #64

Open
pirate opened this issue May 21, 2024 · 1 comment

Comments

@pirate
Copy link

pirate commented May 21, 2024

I have a pydantic model that has a field like so:

class MySchemaModel(BaseModel):
    my_mapping: Dict[str, str] = Field(default={})

DEFAULT = MySchemaModel()

class Model(models.Model):
    test_field: MySchemaModel = SchemaField(default=DEFAULT)

This field contains a mapping of str to str and I Want users to be able to add their own entries , but the default contains no pre-defined keys/properties, so it throws an error right now:

Error: Error while creating EditorState: Invalid schema: Schema of type 'object' must have at least one of these keys: ['properties' or 'keys' or 'oneOf' or 'anyOf' or 'allOf']

I think the issue can be fixed by adding an empty properties: {} entry to the schema generation /conversion code before it gets passed to django-jsonform:
MySchemaModel().model_json_schema()

{
    "properties": {
        "my_mapping": {
            "additionalProperties": {
                "type": "string"
            },
            "default": {},
            "title": "My Mapping",
+           "properties": {},
            "type": "object"
        }
    },
    "title": "MySchemaModel",
    "type": "object"
}

I think django-jsonform should also natively support objects with no properties/keys defined if they have additionalProperties set. I commented on a related an issue on their side here: bhch/django-jsonform#144.

@pirate
Copy link
Author

pirate commented May 21, 2024

As a workaround I've monkey-patched JSONFormWidget to achieve the desired behavior:

from django.contrib import admin

from django_jsonform.widgets import JSONFormWidget
from django_pydantic_field.v2.fields import PydanticSchemaField

from project.models import Dependency


def patch_schema_for_jsonform(schema):
    """recursively patch a schema dictionary in-place to fix any missing properties/keys on objects"""

    # base case: schema is type: "object" with no properties/keys
    if schema.get('type') == 'object' and not ('properties' in schema or 'keys' in schema):
        if 'default' in schema and isinstance(schema['default'], dict):
            schema['properties'] = {
                key: {"type": "string", "default": value}
                for key, value in schema['default'].items()
            }
            # setting the actual value as a default on a hardcoded property is still not ideal as it doesn't allow the user to remove this entry from the UI, but at least it shows up
        else:
            schema['properties'] = {}

    # recursive case: iterate through all values and process any sub-objects
    for key, value in schema.items():
        if isinstance(value, dict):
            patch_schema_for_jsonform(value)



class PatchedJSONFormWidget(JSONFormWidget):
    def get_schema(self):
        self.schema = super().get_schema()
        patch_schema_for_jsonform(self.schema)
        return self.schema



class DependencyAdmin(admin.ModelAdmin):
    formfield_overrides = {PydanticSchemaField: {"widget": PatchedJSONFormWidget}}

admin.site.register(Dependency, DependencyAdmin)

Taken from my pydantic-pkgr code for editing this BinProvider model in the UI: https://github.com/ArchiveBox/pydantic-pkgr/blob/main/pydantic_pkgr/binprovider.py#L171

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant