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

Implemented FieldsArrayField in models #663

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion djongo/models/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
These are the main fields for working with MongoDB.
"""

# THIS FILE WAS CHANGED ON - 28 Mar 2022
# THIS FILE WAS CHANGED ON - 17 Apr 2023

import functools
import json
Expand Down Expand Up @@ -266,6 +266,60 @@ def to_python(self, value):
return processed_value


class FieldsArrayField(Field):
"""
Implements array of the fields inside the document.

To put inside the document correctly, put the base field inside the constructor.
To instanciate the document with corresponding field, put python list as argument.
"""
description = "Field of the field array"

def __init__(self, base_field=None, *args, **kwargs):
if not base_field:
raise ValueError('You must specify a base_field')
self.base_field = base_field
super().__init__(*args, **kwargs)

def db_type(self, connection):
return '{}[]'.format(self.base_field.db_type(connection=connection))

def from_db_value(self, value, expression, connection):
if value is None:
return []
return value

def to_python(self, value):
if isinstance(value, list):
return [self.base_field.to_python(val) for val in value]
elif value is None:
return []
elif isinstance(value, str):
# If the value is a string, try to parse it as a JSON array
try:
value = json.loads(value)
return [self.base_field.to_python(val) for val in value]
except ValueError:
pass
raise ValidationError("Invalid value for ArrayField")

def get_prep_value(self, value):
if isinstance(value, list):
return [self.base_field.get_prep_value(val) for val in value]
elif value is None:
return []
else:
return json.dumps([self.base_field.get_prep_value(val) for val in value])

def formfield(self, **kwargs):
defaults = {
'form_class': forms.CharField,
'widget': forms.Textarea(attrs={'rows': 2}),
}
defaults.update(kwargs)
return super().formfield(**defaults)


class FormedField(ModelField):

def __init__(self,
Expand Down