Comments (4)
Hello, that's wonderful!
Post your patch, right now i don't have much time, but later i will apply it.
from django-mongoengine.
EmbeddedFields patch:
diff -rupN django-mongoengine.orig/django_mongoengine/forms/field_generator.py django-mongoengine/django_mongoengine/forms/field_generator.py
--- django-mongoengine.orig/django_mongoengine/forms/field_generator.py 2015-09-29 16:15:11.230067258 +0200
+++ django-mongoengine/django_mongoengine/forms/field_generator.py 2015-09-29 16:18:40.230067804 +0200
@@ -10,7 +10,7 @@ except ImportError:
from mongoengine import ReferenceField as MongoReferenceField
-from fields import MongoCharField, ReferenceField, DocumentMultipleChoiceField, DictField
+from fields import MongoCharField, ReferenceField, DocumentMultipleChoiceField, DictField, EmbeddedDocumentField
BLANK_CHOICE_DASH = [("", "---------")]
@@ -289,6 +289,18 @@ class MongoFormFieldGenerator(object):
}
return DictField(**defaults)
+ def generate_embeddeddocumentfield(self, field, **kwargs):
+ from documents import documentform_factory
+ defaults = {
+ 'label': self.get_field_label(field),
+ 'help_text': self.get_field_help_text(field),
+ }
+ form_class = EmbeddedDocumentField
+ defaults.update(kwargs)
+ form = form_class(documentform_factory(field.document_type), **defaults)
+ return form
+
+
class MongoDefaultFormFieldGenerator(MongoFormFieldGenerator):
"""This class generates Django form-fields for mongoengine-fields."""
diff -rupN django-mongoengine.orig/django_mongoengine/forms/fields.py django-mongoengine/django_mongoengine/forms/fields.py
--- django-mongoengine.orig/django_mongoengine/forms/fields.py 2015-09-29 16:15:11.230067258 +0200
+++ django-mongoengine/django_mongoengine/forms/fields.py 2015-09-29 16:15:42.060067338 +0200
@@ -5,12 +5,11 @@ from django.utils.encoding import smart_
from django.utils.translation import ugettext_lazy as _
from django_mongoengine.utils import force_text
-from django_mongoengine.forms.widgets import Dictionary
+from django_mongoengine.forms.widgets import Dictionary, EmbeddedFieldWidget
from bson.objectid import ObjectId
from bson.errors import InvalidId
-
class MongoChoiceIterator(object):
def __init__(self, field):
self.field = field
@@ -231,3 +230,34 @@ class DictField(forms.Field):
raise ValidationError(self.error_messages['illegal'] % self.illegal_characters)
if isinstance(v, dict):
self.validate(v, depth + 1)
+
+class EmbeddedDocumentField(forms.MultiValueField):
+ def __init__(self, form, *args, **kwargs):
+ self.form = form()
+ # Set the widget and initial data
+ kwargs['widget'] = EmbeddedFieldWidget(self.form.fields)
+ kwargs['initial'] = [f.initial for f in self.form.fields.values()]
+ kwargs['require_all_fields'] = False
+ super(EmbeddedDocumentField, self).__init__(fields=tuple([f for f in self.form.fields.values()]), *args, **kwargs)
+
+ def bound_data(self, data, initial):
+ return data
+
+ def prepare_value(self, value):
+ return value
+ def compress(self, data_list):
+ data = {}
+ if data_list:
+ data = dict((f.name, data_list[i]) for i, f in enumerate(self.form))
+ f = self.form.__class__(data)
+ f.is_valid()
+ return f.cleaned_data
+ return data
+
+ def clean(self, value):
+ return self.to_python(super(EmbeddedDocumentField, self).clean(value))
+
+ def to_python(self, value):
+ obj = self.form._meta.model()
+ [ obj.__setattr__(k, value[k]) for k in value.keys() ]
+ return obj
diff -rupN django-mongoengine.orig/django_mongoengine/forms/widgets.py django-mongoengine/django_mongoengine/forms/widgets.py
--- django-mongoengine.orig/django_mongoengine/forms/widgets.py 2015-09-29 16:15:11.240067258 +0200
+++ django-mongoengine/django_mongoengine/forms/widgets.py 2015-09-29 16:15:42.060067338 +0200
@@ -370,3 +370,48 @@ class StaticSubDictionary(SubDictionary)
return """
<li><span class="static_key %(html_class)s">%(key)s</span> : %(widgets)s</li>
""" % params
+
+class EmbeddedFieldWidget(MultiWidget):
+ """
+ A widget that render each field found in the supplied form.
+ """
+ def __init__(self, fields, attrs=None):
+ self.fields = fields
+ super(EmbeddedFieldWidget, self).__init__([f.widget for f in self.fields.values()], attrs)
+
+ def decompress(self, value):
+ """
+ Retreieve each field value or provide the initial values
+ """
+ if value:
+ return [value.__getitem__(field) for field in self.fields.keys()]
+ return [field.field.initial for field in self.fields.values()]
+
+ def format_label(self, field, counter):
+ """
+ Format the label for each field
+ """
+ return '<label for="id_formfield_%s" %s>%s:</label>' % (
+ counter, field.required and 'class="required"', field.label)
+
+ def format_help_text(self, field, counter):
+ """
+ Format the help text for the bound field
+ """
+ if field.help_text != None:
+ return '(<em>%s</em>)' % field.help_text
+ return ''
+
+ def format_output(self, rendered_widgets):
+ """
+ This output will yeild all widgets grouped in a un-ordered list
+ """
+ ret = ['<ul class="formfield">']
+ for i, field in enumerate(self.fields):
+ label = self.format_label(self.fields[field], i)
+ help_text = self.format_help_text(self.fields[field], i)
+ ret.append('<li>%s %s %s</li>' % (
+ label, help_text, rendered_widgets[i]))
+
+ ret.append('</ul>')
+ return u''.join(ret)
It works with auto model form generator and defining a form with a formfield. In example:
models
class ContactInfo(fields.EmbeddedDocument):
web = fields.URLField(help_text=_("""List of languages for your application (the first one will be the default language)"""))
email = fields.EmailField(verbose_name=_('e-mail address'))
phone = fields.StringField(verbose_name=_('phone number'))
class Application(Document):
name = fields.StringField(max_length=255, required=True)
contact = fields.EmbeddedDocumentField(ContactInfo)
LOCALES = (('es', 'Spanish'), ('en', 'English'), ('de', 'German'), ('fr', 'French'), ('it', 'Italian'), ('ru', 'Russian'))
locales = fields.ListField(fields.StringField(choices=LOCALES), help_text=_("""List of languages for your application (the first one will be the default language)"""))
forms
class ContactInfoForm(DocumentForm):
class Meta:
document = ContactInfo
widgets = {
'web': URLInput(attrs={'class': 'form-control'}),
'email': EmailInput(attrs={'class': 'form-control'}),
'phone': TextInput(attrs={'class': 'form-control'})
}
class ApplicationForm(DocumentForm):
contact = forms.fields.EmbeddedDocumentField(ContactInfoForm)
class Meta:
document = Application
fields = ('name', 'locales', 'contact')
widgets = {
'name': TextInput(attrs={'class': 'form-control', 'required': 'required'}),
'locales': SelectMultiple(attrs={'class': 'form-control chosen-select', 'required': 'required'})
}
Of course, it also works with embedded documents inside embedded documents... :P
The next feature I would like to implement is a wrapper for the model fields generator that could handle the widget attr.
from django-mongoengine.
Well, it seems that it works fine, but I can not save files inside embedded fields, do you know how could we do it?
from django-mongoengine.
I have no idea.
from django-mongoengine.
Related Issues (20)
- How does the Permission are automatically made in auth module? HOT 1
- get_deleted_objects needs to be changed for admin view HOT 1
- Appconfig models is empty OrderedDict HOT 4
- Too slow with >1K documents! HOT 2
- unable to createsuperuser HOT 1
- Sub query using mongoengine
- fixes for django:3.1 import FieldDoesNotExist
- FieldDoesNotExist import Exception HOT 1
- there are many RemovedInDjango40Warning warnings HOT 2
- something wrong with django_mongoengine/forms/document_options.py HOT 4
- mongo-admin from django_mongoengine not supporting FieldList. Throwing ValidationError for list HOT 3
- Cannot import EMPTY_CHANGELIST_VALUE in django VERSION = (3, 0, 8, 'final', 0) HOT 2
- Is this package still maintained? HOT 1
- django.core.exceptions.ImproperlyConfigured HOT 1
- Admin pagination seems to be off by one. HOT 2
- Do not recommend djongo in the readme. HOT 1
- Is this project alive? HOT 4
- UI issue HOT 2
- Using list in a "not_contains" query HOT 1
- ModuleNotFoundError: No module named 'typing_extensions' HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-mongoengine.