GithubHelp home page GithubHelp logo

jschrewe / django-mongodbforms Goto Github PK

View Code? Open in Web Editor NEW
86.0 11.0 95.0 910 KB

Django forms for mongodb documents

Home Page: http://www.schafproductions.com/projects/django-mongodb-forms/

License: BSD 3-Clause "New" or "Revised" License

Python 100.00%

django-mongodbforms's Introduction

django mongodbforms

This is an implementation of django's model forms for mongoengine documents.

Requirements

Supported field types

Mongodbforms supports all the fields that have a simple representation in Django's formfields (IntField, TextField, etc). In addition it also supports ListFields and MapFields.

File fields

Mongodbforms handles file uploads just like the normal Django forms. Uploaded files are stored in GridFS using the mongoengine fields. Because GridFS has no directories and stores files in a flat space an uploaded file whose name already exists gets a unique filename with the form <filename>_<unique_number>.<extension>.

Container fields

For container fields like ListFields and MapFields a very simple widget is used. The widget renders the container content in the appropriate field plus one empty field. This is mainly done to not introduce any Javascript dependencies, the backend code will happily handle any kind of dynamic form, as long as the field ids are continuously numbered in the POST data.

You can use any of the other supported fields inside list or map fields. Including FileFields which aren't really supported by mongoengine inside container fields.

Usage

mongodbforms supports forms for normal documents and embedded documents.

Normal documents

To use mongodbforms with normal documents replace djangos forms with mongodbform forms.

from mongodbforms import DocumentForm

class BlogForm(DocumentForm)
    ...

Embedded documents

For embedded documents use EmbeddedDocumentForm. The Meta-object of the form has to be provided with an embedded field name. The embedded object is appended to this. The form constructor takes a couple of additional arguments: The document the embedded document gets added to and an optional position argument.

If no position is provided the form adds a new embedded document to the list if the form is saved. To edit an embedded document stored in a list field the position argument is required. If you provide a position and no instance to the form the instance is automatically loaded using the position argument.

If the embedded field is a plain embedded field the current object is simply overwritten.

# forms.py
from mongodbforms import EmbeddedDocumentForm
    
class MessageForm(EmbeddedDocumentForm):
    class Meta:
	    document = Message
	    embedded_field_name = 'messages'
    
	    fields = ['subject', 'sender', 'message',]

# views.py

# create a new embedded object
form = MessageForm(parent_document=some_document, ...)
# edit the 4th embedded object
form = MessageForm(parent_document=some_document, position=3, ...)

Documentation

In theory the documentation Django's modelform documentation should be all you need (except for one exception; read on). If you find a discrepancy between something that mongodbforms does and what Django's documentation says, you have most likely found a bug. Please report it.

Form field generation

Because the fields on mongoengine documents have no notion of form fields mongodbform uses a generator class to generate the form field for a db field, which is not explicitly set.

To use your own field generator you can either set a generator for your whole project using MONGODBFORMS_FIELDGENERATOR in settings.py or you can use the formfield_generator option on the form's Meta class.

The default generator is defined in mongodbforms/fieldgenerator.py and should make it easy to override form fields and widgets. If you set a generator on the document form you can also pass two dicts field_overrides and widget_overrides to __init__. For a list of valid keys have a look at MongoFormFieldGenerator.

# settings.py

# set the fieldgeneretor for the whole application
MONGODBFORMS_FIELDGENERATOR = 'myproject.fieldgenerator.GeneratorClass'

# generator.py
from mongodbforms.fieldgenerator import MongoFormFieldGenerator
	
class MyFieldGenerator(MongoFormFieldGenerator):
	...

# forms.py
from mongodbforms import DocumentForm
	
from generator import MyFieldGenerator
	
class MessageForm(DocumentForm):
    class Meta:
		formfield_generator = MyFieldGenerator

django-mongodbforms's People

Contributors

audreyfeldroy avatar bahus avatar feliperyan avatar flisky avatar gnublade avatar jmbarbier avatar jschrewe avatar laurentpayot avatar mgerring avatar naisonsouza avatar olivierlefloch avatar rafaelnovello avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-mongodbforms's Issues

Feature request: MapField

Just because I use lots of MapFields ;) And because MapField shouldn't be so different from ListField (group of couples of CharField + other field type). That would be SO useful.

Maximum Recursion Depth Exceeded error when upgrading from 0.2 to 0.3

I've been using MongoDbForms on a large project for quite a while and it's working great! Thanks! However, when I updated to the latest version (0.3), it's causing a maximum recursion depth exceeded error sitewide, with no real clarity in the stacktrace. Do you have any thoughts on why this might be occurring?

Thanks!

Lucas

requirements / dependancies woes

Hi,

doing pip -e git+https://github.com/jschrewe/django-mongodbforms.git@master#egg=mongodbforms-dev installs the 0.2 version of mongodbforms, which is completety outdated, and makes the admin crash.

We have to manually pip install -e git+https://github.com/jschrewe/django-mongodbforms.git@master#egg=mongodbforms-dev, which will install another version next to the 0.2โ€ฆ

I think you should perhaps remove the dependancy from setup.py during development and reinstall it when publishing a new release, or just publish a new Pypi release for mongodbforms.

regards,

Documents _post_clean() does not handle None to EMPTY_VALUES conversion gracefully

If the DocumentForm has an optional StringField with no data value specified for it on the form instance, it will fail with;

StringField only accepts string values

This is because on documents.py#L439, a call is being made to validate() on the model field which in raises an exception.

Mongoengine handles this in save() by simply removing the field during to_mongo() as seen in mongoengine:document.py#L248.

Here's a few ideas on how it could be fixed;

  • Prevent .validate() from being called on fields which are not specified in data
  • Ignore any validation errors if the field is optional and the value is None
  • Convert None to the necessary 'empty value' required for each field type
  • Modify _get_validation_exclusions() to support excluding this condition

All of the above could have cascading consequences, and it's not clear which is the correct way forward.

Thoughts?

fields StringFiels & ListFields

i was use DocumentForm to get form

bug StringField regex argument not support ?
and my ListFiels(StringField() ) was not create form field

Invalid handling of 'None' for required ReferenceField

I have a required ReferenceField that presents its choices using a RadioSelect widget. If the user doesn't select a choice and submits the form, I get a ValidationError:

ValidationError: [u'Select a valid choice. 50ab4e5e5ce08a165b81504a is not one of the available choices.']

The problem lies in the ReferenceField.clean method:

def clean(self, value):
    if value in EMPTY_VALUES and not self.required:
        return None

    try:
        oid = ObjectId(value)
        oid = super(ReferenceField, self).clean(oid)

        queryset = self.queryset.clone()
        obj = queryset.get(id=oid)
    except (TypeError, InvalidId, self.queryset._document.DoesNotExist):
        raise forms.ValidationError(self.error_messages['invalid_choice'] % {'value':value})
    return obj

It tries to create an ObjectId from None, which doesn't throw an exception, but creates a new ObjectId. When calling the referenced field's clean method it obviously can't find the passed ObjectId and throws a ValidationError.

One solution is to rewrite the empty values check:

if value in EMPTY_VALUES:
    if self.required:
        raise forms.ValidationError(self.error_messages['required'])
    else:
        return None

DocumentForm save error: object has no attribute 'cleaned_data'

pip freeze

(deco_env)โžœ speechtv pip freeze
Django==1.4.2
mongodbforms==0.3
mongoengine==0.8.3
pymongo==2.7.1

Form
class SpeechTVForm(DocumentForm):
    class Meta:
        document = SpeechTV
        fields = ['source_link', 'embed', 'share_author']
SpeechTV Document
class SpeechTV(Document):
    title = StringField(max_length=30)
    source_link = StringField()
    embed = StringField()
    intro = StringField()
    share_author = StringField()
    ...more...
view.py
def share(request):
    if request.method == 'POST':
        form = SpeechTVForm(request.POST) 
        form.save()
when i post form, show this error message:

Request Method: POST
Request URL: http://127.0.0.1:8000/submit_speech.tv
Django Version: 1.4.2
Python Executable: /Users/denger/Workspaces/Works/deco_workspace/deco_env/bin/python
Python Version: 2.7.3
Python Path: ['/Users/denger/Dropbox/Codes/speechtv',/Users/denger/Workspaces/Works/deco_workspace/deco_env/lib/python2.7/site-packages/PIL']
Installed Applications:

Traceback:
File "/Users/denger/Workspaces/Works/deco_workspace/deco_env/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
111 . response = callback(request, _callback_args, *_callback_kwargs)
File "/Users/denger/Dropbox/Codes/speechtv/speechtv/views.py" in share
26 . form.save()
File "/Users/denger/Workspaces/Works/deco_workspace/deco_env/lib/python2.7/site-packages/mongodbforms/documents.py" in save
533 . fail_message, commit, construct=False)
File "/Users/denger/Workspaces/Works/deco_workspace/deco_env/lib/python2.7/site-packages/mongodbforms/documents.py" in save_instance
178 . instance = construct_instance(form, instance, fields, exclude)
File "/Users/denger/Workspaces/Works/deco_workspace/deco_env/lib/python2.7/site-packages/mongodbforms/documents.py" in construct_instance
98 . cleaned_data = form.cleaned_data

Exception Type: AttributeError at /submit_speech.tv
Exception Value: 'SpeechTVForm' object has no attribute 'cleaned_data'
Request information:
GET: No GET data

POST:
source_link = u'sfasfsafsafasf'
csrfmiddlewaretoken = u'ppHzHO8TREgHfKBGobdk7UlW7OvFnICA'
embed = u'afsdfasfasd'
share_author = u'afd'

Can't store single EmbeddedDocument in a parent.

I'm not positive, but I think I'm trying something that that hasn't been tested or coded for. In a recent issue you stated that EmbeddedDocuments are normally held in lists, but to my reading of the MongoEngine API that isn't required.

I'm using EmbeddedDocuments to break up some of our data into easier to deal with portions. But when I try to open the form for the EmbeddedDocument I get a FieldError and "Parent document must have field ...". My parent document does have the named field (microarch), but it is not listed in an _embedded_field attribute as the check for this exception assumes. The field is listed with all the other fields and has the type EmbeddedDocument. I'll try to copy in the related code I have below.

models.py

class MicroArch(EmbeddedDocument):
    ...

class CPU(Document):
    ...
    microarch = EmbeddedDocumentField(MicroArch)

forms.py

class CpuAddForm(DocumentForm):
    class Meta:
        document = CPU
        fields = ['company', 'model', 'codename', 'isa', 'tapeout', 'process_node']

class MicroArchAddForm(EmbeddedDocumentForm):
    class Meta:
        document = MicroArch
        embedded_field_name = 'microarch'
        fields = ['pipeline_stages', 'decode_width', 'is_ooo', 'ooo_depth', 'peak_execution_slots', 'vector_int_width',
                'vector_fp_sp_width', 'vector_fp_dp_width', 'pipeline_mispredict_latency', 'dram_latency',
                'addressable_system_memory', 'peak_sp_gflops', 'peak_dp_gflops']

views.py

class CpuAdd(View):
    def get(self, request):
        context = {'form': CpuAddForm()}
        context.update(csrf(request))
        return render(request, 'cpu_add.html', context)

    def post(self, request):
        form = CpuAddForm(request.POST)  # A form bound to the POST data
        if form.is_valid():  # All validation rules pass
            ...
            cpu1 = CPU(...)
            cpu1.save()
            return redirect(reverse('microarch-add', kwargs={'pk': cpu1.pk}))
        else:
            context = {'form': CpuAddForm(),
                       'messages': 'Invalid input'}
            context.update(csrf(request))
            return render(request, 'cpu_add.html', context)

class MicroArchAdd(View):
    def get(self, request, pk):  # get an error if I don't put the pk here.
        context = {}
        # cpu1 = CPU.object.filter(pk__iexact=self.kwargs['pk'])
        cpu1 = CPU.objects.filter(pk__iexact=pk)
        if cpu1:
            maform = MicroArchAddForm(parent_document=cpu1)  # TODO: Get "Parent document must have field microarch" error now
                ...

And I get the error at that last line when trying to make a blank form object that points back at the CPU that was just made.

python 3.x support

Django 1.5 and MongoEngine 0.7 both support python 3.x. To use mongodbforms with them I tried to make trivial changes to source code (removing u prefix from strings, exceptions "as e:", dot prefix to modules, etc.) but now it's a bit tricky as the "new" module used in util.py is depreciated in python 3.
I'm far from a python expert and I don't know the mongodbforms internals so I had to stop there, but making mongodbforms compatible with python 3.x would be really sweet and it shouldn't be too hard. It would make my day for sure. Thanks everyone.

ListField 'NoneType' object has no attribute 'append'

I'm getting 'NoneType' object has no attribute 'append' when I try and render the following ListField using the default generator and widget.

choices = ListField(field=StringField(max_length=200))

My form

class ProductFieldForm(DocumentForm):
    class Meta:
        document = ProductField

        fields = ['name', 'description', 'required', 'widget', 'choices', 'variable', 'weight']

Django error message

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/staff/add-product-field/

Django Version: 1.5.1
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'south',
 'djcelery',
 'post_office',
 'accounts',
 'project_name',
 'mongodbforms')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Template error:
In template /Users/andrew/Projects/project_name/site/templates/staff/add_product_field.html, error at line 6
   'NoneType' object has no attribute 'append'
   1 : {% extends "base.html" %}
   2 : 
   3 : {% block title %}Add Product Field{% endblock %}
   4 :
   5 : {% block content %}
   6 :    {{ form.as_p }} 
   7 : {% endblock %}

Traceback:
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  86.         return handler(request, *args, **kwargs)
File "/Users/andrew/Projects/project_name/site/project_name/staff/views.py" in get
  35.         return render(request, self.template_name, {'form': form})
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/shortcuts/__init__.py" in render
  53.     return HttpResponse(loader.render_to_string(*args, **kwargs),
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
  177.         return t.render(context_instance)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in render
  140.             return self._render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in _render
  134.         return self.nodelist.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in render
  830.                 bit = self.render_node(node, context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/debug.py" in render_node
  74.             return node.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  124.         return compiled_parent._render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in _render
  134.         return self.nodelist.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in render
  830.                 bit = self.render_node(node, context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/debug.py" in render_node
  74.             return node.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  63.             result = block.nodelist.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in render
  830.                 bit = self.render_node(node, context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/debug.py" in render_node
  74.             return node.render(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/debug.py" in render
  84.             output = self.filter_expression.resolve(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in resolve
  578.                 obj = self.var.resolve(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in resolve
  728.             value = self._resolve_lookup(context)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/template/base.py" in _resolve_lookup
  779.                             current = current()
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/forms/forms.py" in as_p
  240.             errors_on_separate_row = True)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/forms/forms.py" in _html_output
  185.                     'field': six.text_type(bf),
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/forms/forms.py" in __str__
  411.         return self.as_widget()
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/django/forms/forms.py" in as_widget
  458.         return widget.render(name, self.value(), attrs=attrs)
File "/Users/andrew/.virtualenvs/project_name/lib/python2.7/site-packages/mongodbforms/widgets.py" in render
  23.         value.append('')

Exception Type: AttributeError at /staff/add-product-field/
Exception Value: 'NoneType' object has no attribute 'append'

Fix

Adding the following on line 20 of widgets.py fixes the issue but I don't want to clone and submit a pull request in case I'm not using the module as intended.

value = [] if value is None else value

Requirements needs updating

We are trying out using mongodbforms 0.2.2 on FreeBSD 9.1 .

We have found that we must have mongoengine 0.8.2 rather than 0.6.8 as the 0.2.2 code uses the attribute _fields_ordered that does not apparently exist in mongoengine 0.6.8 .

Our version of Django is 1.4.3 .

unexpected keyword argument 'min_length'

After the 10th of July commit whatever I do I get unexpected keyword argument 'min_length' errors:

Traceback (most recent call last):
  File "/usr/local/lib/python3.3/dist-packages/django/core/urlresolvers.py", line 339, in urlconf_module
    return self._urlconf_module
AttributeError: 'RegexURLResolver' object has no attribute '_urlconf_module'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):

(...)

  File "/opt/publiberty/django/www/forms.py", line 26, in 
    class MediaForm(DocumentForm):
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/documents.py", line 313, in __new__
    opts.exclude, opts.widgets, formfield_callback, formfield_generator)
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/documents.py", line 263, in fields_for_document
    formfield = field_generator.generate(f, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/fieldgenerator.py", line 390, in generate
    return super(MongoDefaultFormFieldGenerator, self).generate(field, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/fieldgenerator.py", line 83, in generate
    return getattr(self, attr_name)(field, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/fieldgenerator.py", line 174, in generate_stringfield
    return form_class(**defaults)
  File "/usr/local/lib/python3.3/dist-packages/django/forms/fields.py", line 810, in __init__
    super(TypedChoiceField, self).__init__(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/forms/fields.py", line 754, in __init__
    initial=initial, help_text=help_text, *args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'min_length'

After reverting to the last 9th of July commit everything is ok.

last commit (df67df4373eac349944b58f93ea74439d4444c46) breaks at least CharField

Hi,

it's me again.

I couldn't understand why a form stopped working a few days ago. I reverted this patch, and now it works again.

The problem occurs on the Folder.name field. In form.cleaned_data the name field is not present anymore after validation, and is_valid() fails. Even If I manually specify a name as Charfield in the form, it doesn't help.

Here is my code. Sorry for the length, the project is becoming huge and there are a lot of things involvedโ€ฆ The actual form handles just the name and parent of the Folder instance. the subscriptions field is a select2 field that helps users to move subscriptions quickly, it doesn't touch the Folder class as you can see. In fact the problem is with name, which is a plain CharField on a simple StringField.

class Folder(Document, DocumentHelperMixin, DocumentTreeMixin):
    name  = StringField(verbose_name=_(u'Name'),
                        unique_with=['owner', 'parent'])
    owner = ReferenceField('User', verbose_name=_(u'Owner'),
                           reverse_delete_rule=CASCADE)

    parent = ReferenceField('self', verbose_name=_(u'Parent folder'),
                            reverse_delete_rule=NULLIFY, required=False)
    children = ListField(ReferenceField('self', reverse_delete_rule=PULL),
                         default=list, verbose_name=_(u'Children folders'))


    def validate(self, *args, **kwargs):

        try:
            super(Folder, self).validate(*args, **kwargs)

        except ValidationError as e:
            parent_error = e.errors.get('parent', None)

            if parent_error and str(parent_error).startswith('Field is requi'):
                # Allow the creation of the root folder whatever it costs,
                # else we cannot create any directory (chicken & egg pbm).
                if self.name == u'__root__':
                    e.errors.pop('parent')

            if e.errors:
                raise e

# [simplified a lotโ€ฆ]

Forms:

class ManageFolderForm(DocumentForm):
    parent = OnlyNameChoiceField(queryset=Folder.objects.all(),
                                 empty_label=_(u'(None)'),
                                 label=_(u'Parent folder'),
                                 required=False, widget=Select2Widget())

    subscriptions = OnlyNameMultipleChoiceField(
        label=_(u'Subscriptions'), queryset=Subscription.objects.none(),
        required=False, widget=Select2MultipleWidget(),
        help_text=_(u'These are the ones held directly by the folder; they '
                    u'are displayed above subfolders. There can be none, if '
                    u'you prefer dispatching your subscriptions in subfolders '
                    u'only.'))

    class Meta:
        model = Folder
        fields = ('name', 'parent', )
        widgets = {
            'name': forms.TextInput(),
        }

    def __init__(self, *args, **kwargs):

        self.folder_owner = kwargs.pop('owner')

        super(ManageFolderForm, self).__init__(*args, **kwargs)

        folders_tree = self.folder_owner.get_folders_tree(for_parent=True)

        if self.instance.id:
            try:
                folders_tree.remove(self.instance)
            except ValueError:
                pass

            else:
                for f in self.instance.children_tree:
                    try:
                        folders_tree.remove(f)

                    except ValueError:
                        # ValueError: list.remove(x): x not in list
                        # Happens when try to remove a level-N+ folder
                        # from a list limited to level N-1 folder. No
                        # need to continue, folders_tree return a
                        # depth-aware list.
                        break

            try:
                self.fields['subscriptions'].initial = \
                    self.folder_owner.subscriptions_by_folder[self.instance]

            except KeyError:
                # No subscriptions in this folder yet.
                pass

        self.fields['parent'].queryset = folders_tree
        self.fields['subscriptions'].queryset = \
            self.folder_owner.subscriptions.order_by('name')

    def clean_parent(self):

        try:
            parent = self.cleaned_data['parent']

        except:
            return self.folder_owner.root_folder

        if parent is None:
            return self.folder_owner.root_folder

        return parent

    def is_valid(self):

        res = super(ManageFolderForm, self).is_valid()

        if not res:
            return False

        if self.instance.id is None:

            parent_folder = self.cleaned_data['parent']

            try:
                Folder.objects.get(
                    owner=self.folder_owner, name=self.cleaned_data['name'],
                    parent=parent_folder)
            except Folder.DoesNotExist:
                return True

            else:
                if parent_folder == self.folder_owner.root_folder:
                    self._errors['already_exists'] = \
                        _(u'A top folder by that name already exists.')
                else:
                    self._errors['already_exists'] = \
                        _(u'A folder by that name already exists '
                          u'at the same place.')

                return False

        return True

    def save(self, commit=True):

        parent_folder  = self.cleaned_data.get('parent')
        parent_changed = False

        # id == None means creation, else we are editing.
        if self.instance.id:

            # We need to get the previous values; Django doesn't cache
            # them and self.instance is already updated with new values.
            old_folder = Folder.objects.get(id=self.instance.id)

            if old_folder.parent != parent_folder:
                # The form.save() will set the new parent, but
                # will not unset instance from parent.children.
                # We need to take care of this.
                try:
                    old_folder.parent.remove_child(self.instance,
                                                   full_reload=False,
                                                   update_reverse_link=False)
                except AttributeError:
                    # A top folder is becoming a sub-folder. It had no parent.
                    pass
                parent_changed = True

        else:
            # In "add folder" mode, parent has always changed, it's new!
            parent_changed = True

        folder = super(ManageFolderForm, self).save(commit=False)

        if self.instance.id is None:
            folder.owner = self.folder_owner

        if commit:
            folder.save()

        if parent_changed:
            # In edit or create mode, we need to take care of the other
            # direction of the double-linked relation. This will imply
            # a superfluous write in case of an unchanged parent
            parent_folder.add_child(folder, full_reload=False,
                                    update_reverse_link=False)

        self.synchronize_subscriptions_folders(folder)

        return folder

    def synchronize_subscriptions_folders(self, folder):
        """ NOTE: `folder` is just self.instance passed
            through to avoid to look it up again. """

        try:
            initial_subscriptions = \
                self.folder_owner.subscriptions_by_folder[self.instance]

        except KeyError:
            initial_subscriptions = []

        updated_subscriptions = self.cleaned_data['subscriptions']

        for subscription in initial_subscriptions:
            if subscription not in updated_subscriptions:
                subscription.update(pull__folders=folder)

        if self.folder_owner.preferences.selector.subscriptions_in_multiple_folders: # NOQA
            subscr_kwargs = {'add_to_set__folders': folder}

        else:
            subscr_kwargs = {'set__folders': [folder]}

        for subscription in updated_subscriptions:
            # This will update more things than needed, but in the case of
            # a changed preference, this will make the subscription appear
            # in one folder only again.
            # TODO: when the preference has a trigger on save() that do
            # this automatically, uncomment the following line to simply
            # move new subscriptions to this folder, and not touch others.
            #
            # if subscription not in initial_subscriptions:
            subscription.update(**subscr_kwargs)

URLs / Views:

    url(_(ur'^folder/(?P<folder>(?:[0-9a-f]{24,24})+)$'),
        login_required(never_cache(views.manage_folder)),
        name='edit_folder'),

def manage_folder(request, **kwargs):
    """ This view does add/edit functions. """

    folder_id = kwargs.pop('folder', None)
    folder    = Folder.get_or_404(folder_id) if folder_id else None
    edit_mode = folder is not None
    user      = request.user.mongo

    if request.POST:
        messages.info(request, u'manage folder POST "%s"' % request.POST,
                      extra_tags='safe')

        if edit_mode:
            messages.info(request, u'manage folder EDIT %s' % folder,
                          extra_tags='safe')

            form = ManageFolderForm(request.POST, instance=folder,
                                    owner=user)

        else:
            form = ManageFolderForm(request.POST, owner=user)

        if form.is_valid():

            try:
                folder = form.save()

            except TreeCycleException, e:
                messages.error(request, _(u'Save <em>{0}</em> '
                               u'failed: {1}').format(folder.name, e),
                               extra_tags=u'safe')

            else:
                messages.info(request, _(u'Folder <em>{0}</em> successfully '
                              u'{1}.').format(folder.name, _(u'modified')
                                              if edit_mode else _(u'created')),
                              extra_tags=u'safe')

        else:
            messages.info(request, u'TEST2', extra_tags='safe')
            messages.warning(request, _(u'Could not {0} folder: {1}.').format(
                             _(u'modify') if edit_mode else _(u'create'),
                             form.errors), extra_tags='sticky safe')

            LOGGER.error(u'%s: %s', form.errors, form.cleaned_data)

        return HttpResponseRedirect(reverse('source_selector')
                                    + (u"#{0}".format(folder.id)
                                       if folder else u''))

    else:
        if not request.is_ajax():
            return HttpResponseBadRequest('Did you forget to do an Ajax call?')

        if folder:
            form = ManageFolderForm(instance=folder, owner=user)

        else:
            form = ManageFolderForm(owner=user)

    return render(request, 'snippets/selector/manage-folder.html',
                  {'form': form, 'folder': folder})

I tried to hunt in the code, but I couldn't find anything obvious making me understand why it fails. In my tests, I edit a folder, so it has a name (which displays fine in the form). If I change the name, the form fails and cleaned_data doesn't have name anymore.

regards,

empty strings for fields are not written in a database

If I edit a document in a form and just clean a string field value eventually the field value in a database is not changed.
I have found that the fix described by

# mongoengine chokes on empty strings for fields
# that are not required. Clean them up here, though
# this is maybe not the right place :-)

prevents updating of emptied fields in the database.
If I comment out "elif value in EMPTY_VALUES:" and "to_delete.append(f.name)" everithing works fine.

I use mongoengine 0.8.3.

Doesn't work with pymongo > 2.2

In pymongo 2.2 the call to import objectid is:

from bson.objectid import ObjectId

instead:

from pymongo.objectid import ObjectId

'QuerySet' object has no attribute '_fields'

Not sure if this is an issue on mongodbforms or I am the problem.

I am trying to autogenerate a form to edit a document from Mongengine. Something like the first example from here: https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
I have this on forms.py

class EditPublicationForm(DocumentForm):
    class Meta:
        document = Publication
        fields = '__all__'

No that I also tried changing fields = 'all' to fields = ['field1', 'field2', ...]

In views.py:

def curator_edit_article(request, record_id=''):
    ''' Show all articles to the curator. Request #434 '''

    if request.method == 'POST':
        form = EditPublicationForm(request.POST)
        if form.is_valid():
            pass # Real content removed to make this short!
    else:
        pub = Publication.objects(id=record_id)
        form = EditPublicationForm(instance=pub)
    return render(request, 'curator_edit_article.html', {'form':form})

When I do a GET request to http://localhost:8000/edit/51799bee2ed3b21a75005a0d/, I get this:

Request Method: GET
Request URL: http://localhost:8000/edit/51799bee2ed3b21a75005a0d/
Django Version: 1.4.2
Exception Type: AttributeError
Exception Value:
'QuerySet' object has no attribute '_fields'
Exception Location: /home/sbassi/projects/catalytic/cata/local/lib/python2.7/site-packages/mongodbforms/documents.py in document_to_dict, line 220

listfields causing 'NoneType' object has no attribute 'choices'

Exception Type: AttributeError
Exception Value: 'NoneType' object has no attribute 'choices'

I am trying to use mongoadmin-0.1.3-py2.7 which is dependent on this package. The only issue I have so far is the error above on any of my models with listfields.

Here is an example of my model:
class packageInfo( Document ):
dateAdded = DateTimeField()
dateLastEdited = DateTimeField()
serverUUID = StringField(required=True)
packageList = ListField()

class Meta:
    using = 'mongodb'

The line it doesn't like is 161 in
https://github.com/jschrewe/django-mongodbforms/blob/master/mongodbforms/documents.py
Which reads like this:

if isinstance(f, ListField) and not (f.field.choices or isinstance(f.field, ReferenceField)):
continue

I was going to submit a patch but I am not sure what use case would match the f.field.choices field properly. If I am doing it wrong please let me know. I am still new to Mongodb and making it work with django.
Thanks
Brian

Some examples

I can't figure out how to make this work :(

I feel weird asking for more help, but hey, I'd gladly add an example folder with a working app if someone provides me with the "views.py" for a working example.

Thanks!

Documents.py line 191 instance is a QueryDict?

Hi guys I updated mongodbforms to the latest edition, I'm getting an error where Documents.py line 191 tells me instance is a QueryDict and it has no attribute '_fields'",)

Any idea why that might be?

mongoadmin not listed as a dependency

mongoadmin is not listed as a dependency but it is imported in line 106 of documentoptions.py.

Is there anyway to get around that dependency? Is that code necessary? I commented out those lines at and I didn't seem to break anything.

AttributeError for unfilled email fields

When I use mongodbforms with a simple dango CreateView and there is an email field (not required) that's not filled, I get:

Internal Server Error: /fr/contact/
Traceback (most recent call last):
File "/usr/local/lib/python3.3/dist-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, _callback_args, *_callback_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 86, in dispatch
return handler(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 194, in post
return super(BaseCreateView, self).post(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 160, in post
return self.form_valid(form)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 136, in form_valid
self.object = form.save()
File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.1.5-py3.3.egg/mongodbforms/documents.py", line 434, in save
fail_message, commit, construct=False)
File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.1.5-py3.3.egg/mongodbforms/documents.py", line 111, in save_instance
instance.save()
File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/document.py", line 227, in save
doc = self.to_mongo()
File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/base/document.py", line 247, in to_mongo
value = field.to_mongo(value)
AttributeError: 'NoneType' object has no attribute 'to_mongo'

(see #25 for models.py, forms.py, and views.py)

Before mongodbforms I used to use my own custom forms with django.forms fields and I could fix empty emails problem by adding a custom form_valid() method in the FeedbackCreate view that would simply delete the email in the cleaned_data:

def form_valid(self, form):
    """This method is called when valid form data has been POSTed. It should return an HttpResponse. Email must have an email representation in model, empty string would cause an error.
    """
    if 'email' in form.cleaned_data and not form.cleaned_data['email']:
        del form.cleaned_data['email']
    return super().form_valid(form)

But now this is not working.

Problem with MapWidget

Hi,
I'm using the MapWidget and I'm having a problem in this line:

value = list(value.items())

When creating an empty MapWidget value is None, so value.items() throws an exception.

A possible fix could be doing something like this, which is working for me:
value = {} if value is None else value

TypeError: __init__() got multiple values for keyword argument 'instance'

After the #51 fix posting is ok but when I try to edit the form I get:

Traceback (most recent call last):
  File "/usr/local/lib/python3.3/dist-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 29, in _wrapper
    return bound_func(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 25, in bound_func
    return func(self, *args2, **kwargs2)
  File "/opt/myproject/django/www/views.py", line 426, in dispatch
    return super().dispatch(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 87, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 224, in get
    return super(BaseUpdateView, self).get(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 160, in get
    form = self.get_form(form_class)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 44, in get_form
    return form_class(**self.get_form_kwargs())
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/documents.py", line 542, in __init__
    super(EmbeddedDocumentForm, self).__init__(data=data, files=files, instance=instance, *args, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'instance'

So I'm still using fb57c72 .

created as new and then saved form has instance with id = None

If a form that is created for a new document has been saved the document still has id = None.
I have found that in documents.py in save_instance procedure in case of len(form._meta._dont_save) > 0.
instance._data is restored after save so id=None is restored as well.
Also if the document has a custom save method that changes data then that data is going to be lost in the form.

DocumentForm metaclass creates connection too early

DocumentFormMetaclass attempts to create a connection too quickly when a class is defined, with at least formfield_generator needing an open connection in order to continue (as seen in the below traceback).

This does not work well because a mongoengine connections might not yet be available at the time the forms.py is imported. For example when running unit tests, the app modules are imported first, and then setup_databases() is called which applies NAME patches to define what the test database name should be. However this breaks when using this library because the DocumentForm requires a connection before we even know what the connection name should be.

The quick fix is to lazy import each form class (i.e. within a method/function local, rather than a module global) but this is quite hacky.

Alternatively you could patch DocumentForm to return a lazy class loader, which doesn't create the new form type until the point where __init__.py is called. This would prevent the class meta being called at import. However anything which relies on introspection of DocumentForm will naturally break when using this approach.

An ideal patch would be to stop mongodbforms from requiring a connection inside formfield_generator, but it would seem this isn't a trivial thing to fix.

Any thoughts?

  File "/home/foxx/code/simplicitymedialtd/smsje-repo/smsje/libs/useful2/testproject/forms.py", line 47, in <module>
    class MessageCreateForm(PartialFormMixin, ReadOnlyFormFieldsMixin, DocumentForm):
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongodbforms/documents.py", line 281, in __new__
    opts.exclude, opts.widgets, formfield_callback, formfield_generator)
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongodbforms/documents.py", line 229, in fields_for_document
    formfield = field_generator.generate(f, **kwargs)            
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongodbforms/fieldgenerator.py", line 401, in generate
    return super(MongoDefaultFormFieldGenerator, self).generate(field, **kwargs)
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongodbforms/fieldgenerator.py", line 83, in generate
    return getattr(self, attr_name)(field, **kwargs)
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongodbforms/fieldgenerator.py", line 308, in generate_referencefield
    'queryset': field.document_type.objects.clone(),
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongoengine/queryset/manager.py", line 37, in __get__
    queryset = queryset_class(owner, owner._get_collection())
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongoengine/document.py", line 148, in _get_collection
    db = cls._get_db()
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongoengine/document.py", line 142, in _get_db
    return get_db(cls._meta.get("db_alias", DEFAULT_CONNECTION_NAME))
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongoengine/connection.py", line 134, in get_db
    conn = get_connection(alias)
  File "/home/foxx/.virtualenvs/smsje/local/lib/python2.7/site-packages/mongoengine/connection.py", line 93, in get_connection
    raise ConnectionError(msg)
mongoengine.connection.ConnectionError: Connection with alias "default-mongo" has not been defined

object has no attribute '_changed_fields'

After commit 5cb3a5b (fixing #48) I get the following internal server error when posting forms:

Traceback (most recent call last):
  File "/usr/local/lib/python3.3/dist-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 29, in _wrapper
    return bound_func(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 25, in bound_func
    return func(self, *args2, **kwargs2)
  File "/opt/myproject/django/www/views.py", line 426, in dispatch
    return super().dispatch(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 87, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 228, in post
    return super(BaseUpdateView, self).post(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 170, in post
    if form.is_valid():
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 129, in is_valid
    return self.is_bound and not bool(self.errors)
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 121, in errors
    self.full_clean()
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 275, in full_clean
    self._post_clean()
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2.2-py3.3.egg/mongodbforms/documents.py", line 396, in _post_clean
    f.name not in self.instance._changed_fields:
AttributeError: 'Book' object has no attribute '_changed_fields'

So I'm sticking to fb57c72 and everything is fine with this old one.

ListField containing ReferenceField's

The current multiple choice widget for ListField(ReferenceField(Foo)) doesn't provide a very good user experience and our team has written jQuery to create an interface that posts data in the same format as a ListField(StringField()).

Our current processing of this data is far from optimal and I wonder how it should be approached?

Thanks,
Andrew

widgets in meta is not working

Currently widgets in Meta class is not considered when generating formfield.

I can see there are two ways to archive this -

  1. pass kwargs to field_generator.generate (which I've used)
  2. use formfield_callback. Can you please give some document on this?

Which way do you pefer? Thanks,

Error when trying to create form from Custom User Model

Exception Value:
'PermissionManager' object has no attribute 'clone'
Exception Location: /Library/Python/2.7/site-packages/mongodbforms/fieldgenerator.py in generate_listfield, line 334

Thats the error I am getting..

views.py:

form = ProfileForm()

forms.py:

class ProfileForm(DocumentForm):

class Meta:
    document = Profile

Is this because mongodbforms doesnt support some of the fields from the user model?

Installing mongodbform through PIP raises HTTP error

Hi,

It's impossible to install the mongodbforms usign pip command

$ pip install mongodbforms

The error is the following:

$ pip install mongodbforms
Downloading/unpacking mongodbforms
  HTTP error 503 while getting https://pypi.python.org/packages/source/m/mongodbforms/mongodbforms-0.2.2.tar.gz#md5=8c608375e66791962966becd62cbaf10 (from https://pypi.python.org/simple/mongodbforms/)
  Could not install requirement mongodbforms because of error HTTP Error 503: Backend is unhealthy
Cleaning up...
Could not install requirement mongodbforms because of HTTP error HTTP Error 503: Backend is unhealthy for URL https://pypi.python.org/packages/source/m/mongodbforms/mongodbforms-0.2.2.tar.gz#md5=8c608375e66791962966becd62cbaf10 (from https://pypi.python.org/simple/mongodbforms/)

'object' object has no attribute '__contains__'

Commit efa1bb1 introduced changes to LazyDocumentMetaWrapper which is now throwing the following error for us.

Any ideas?
Andrew

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8001/users/products/edit/viber-stretch-dress/

Django Version: 1.6
Python Version: 2.7.5
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'gunicorn',
 'south',
 'djcelery',
 'mongodbforms',
 'bootstrapform',
 'post_office',
 'extra_views',
 'tastypie',
 'redirect',
 'accounts',
 'aws_upload',
 'staff',
 'project',
 'products',
 'advertisers',
 'project_custom_tags',
 'api',
 'debug_toolbar')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware')


Traceback:
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  90.                 response = middleware_method(request)
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/importlib.py" in import_module
  40.         __import__(name)
File "/Users/andrew/Projects/project/site/project/project/urls.py" in <module>
  38.     (r'^staff/', include('staff.urls')),
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/conf/urls/__init__.py" in include
  26.         urlconf_module = import_module(urlconf_module)
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/importlib.py" in import_module
  40.         __import__(name)
File "/Users/andrew/Projects/project/site/project/staff/urls.py" in <module>
  2. from staff.views import *
File "/Users/andrew/Projects/project/site/project/staff/views.py" in <module>
  4. from staff.forms import (
File "/Users/andrew/Projects/project/site/project/staff/forms.py" in <module>
  92. class ProductCategoryForm(DocumentForm):
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongodbforms/documents.py" in __new__
  309.             getattr(new_class, 'Meta', None)
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongodbforms/documents.py" in __init__
  276.             self.document._meta = DocumentMetaWrapper(self.document)
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongodbforms/documentoptions.py" in __init__
  146.         if 'id_field' in self._meta:
File "/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongodbforms/documentoptions.py" in __contains__
  95.         return self._wrapped.__contains__(key)

Exception Type: AttributeError at /users/products/edit/viber-stretch-dress/
Exception Value: 'object' object has no attribute '__contains__'

Not working with Python 3.X

I'm using Python 3.3 with latest django-trunk, mongoengine and pymongo versions from github.

I had some "ImportError: cannot import name smart_unicode", same for force_unicode.
I just commented the import line of these two functions and replaced them by functions doing nothing.

I'm trying to make it work using a simple CreateView:

forms.py

class FeedbackForm(DocumentForm):
class Meta:
model = Feedback
fields = ['name', 'email', 'subject', 'message']

views.py

class FeedbackCreate(CreateView):
model = Feedback
form_class = FeedbackForm

model.py

class Feedback(Document):
name = StringField(max_length=120)
email = EmailField()
subject = StringField(max_length=120)
message = StringField(max_length=1000, required=True)
meta = {'allow_inheritance': False, 'indexes': ['id']}

But all I get is:

Internal Server Error: /fr/contact/
Traceback (most recent call last):
File "/usr/local/lib/python3.3/dist-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, _callback_args, *_callback_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 86, in dispatch
return handler(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 190, in get
return super(BaseCreateView, self).get(request, _args, *_kwargs)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 149, in get
form = self.get_form(form_class)
File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 37, in get_form
return form_class(**self.get_form_kwargs())
File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.1.5-py3.3.egg/mongodbforms/documents.py", line 268, in init
raise ValueError('DocumentForm has no document class specified.')
ValueError: DocumentForm has no document class specified.

DocumentMultipleChoiceField bug when unique_with is used

I have Book objects that can have several Author objects:

class Book(Document):
    id = SequenceField(primary_key=True, verbose_name=_("book ID"))
    title = StringField(max_length=200, required=True, verbose_name=_("title"), unique_with=['authors', 'language'])
    authors = ListField(ReferenceField(Author, dbref=False, reverse_delete_rule=CASCADE), required=True, verbose_name=_("authors"))
    language = StringField(max_length=2, required=True, choices=LANGUAGES, verbose_name=_("language"))

In my Book form I have:

    authors = DocumentMultipleChoiceField(queryset=Author.objects.order_by('+last_name').all(),
                                          label=Book.authors.verbose_name,
                                          help_text=_("(you can select multiple authors)"))

If I use unique_with for the title field like described above, when I try to save the form I get:

Internal Server Error:
Traceback (most recent call last):
  File "/usr/local/lib/python3.3/dist-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 29, in _wrapper
    return bound_func(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/utils/decorators.py", line 25, in bound_func
    return func(self, *args2, **kwargs2)
  File "/opt/publiberty/django/www/views.py", line 409, in dispatch
    return super().dispatch(*args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/base.py", line 87, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 228, in post
    return super(BaseUpdateView, self).post(request, *args, **kwargs)
  File "/usr/local/lib/python3.3/dist-packages/django/views/generic/edit.py", line 170, in post
    if form.is_valid():
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 128, in is_valid
    return self.is_bound and not bool(self.errors)
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 120, in errors
    self.full_clean()
  File "/usr/local/lib/python3.3/dist-packages/django/forms/forms.py", line 274, in full_clean
    self._post_clean()
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2-py3.3.egg/mongodbforms/documents.py", line 468, in _post_clean
    self.validate_unique()
  File "/usr/local/lib/python3.3/dist-packages/mongodbforms-0.2-py3.3.egg/mongodbforms/documents.py", line 490, in validate_unique
    if len(qs) > 0:
  File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/queryset/queryset.py", line 131, in __len__
    list(self._iter_results())
  File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/queryset/queryset.py", line 164, in _iter_results
    self._populate_cache()
  File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/queryset/queryset.py", line 174, in _populate_cache
    self._result_cache.append(next(self))
  File "/usr/local/lib/python3.3/dist-packages/mongoengine-0.8.2-py3.3.egg/mongoengine/queryset/queryset.py", line 1165, in __next__
    raw_doc = next(self._cursor)
  File "/usr/local/lib/python3.3/dist-packages/pymongo-2.5.1_-py3.3-linux-x86_64.egg/pymongo/cursor.py", line 819, in __next__
    if len(self.__data) or self._refresh():
  File "/usr/local/lib/python3.3/dist-packages/pymongo-2.5.1_-py3.3-linux-x86_64.egg/pymongo/cursor.py", line 768, in _refresh
    self.__uuid_subtype))
bson.errors.InvalidDocument: Cannot encode object: <Author: Verne, Jules>

When I don't use unique_with everything works great.

UnboundLocalError in documents.py at line 919

Hi there.

I'm using mongodbforms for my Django application. I have a ListField of EmbeddedDocumentField and need to make a form out of it (Using embeddedformset_factory.). However the code won't run, returning the following error :

File "/home/jacques/.ve/ve_1/lib/python2.7/site-packages/mongodbforms/documents.py", line 919, in _get_embedded_field if (isinstance(field, EmbeddedDocumentField) and field.document_type == document) or \ UnboundLocalError: local variable 'field' referenced before assignment

So, after a very quick investigation, I found out the following piece of code inside mongodbforms/documents.py (line 917) :

        emb_fields = [
            f for f in parent_doc._fields.values()
            if (isinstance(field, EmbeddedDocumentField) and field.document_type == document) or \
            (isinstance(field, ListField) and
             isinstance(field.field, EmbeddedDocumentField) and 
             field.field.document_type == document)
        ]

...Which seems quite incorrect to me, because field is never instantiated in the loop. Hence, I patched it this way, replacing field with f :

        emb_fields = [
            f for f in parent_doc._fields.values()
            if (isinstance(f, EmbeddedDocumentField) and f.document_type == document) or \
            (isinstance(f, ListField) and
             isinstance(f.field, EmbeddedDocumentField) and 
             f.field.document_type == document)
        ]

Which now works properly. Is it possible to update the source ? (I'm not too familiar with Git so I don't want to make a mess of it.)

Have a nice day !

DocumentMultipleChoiceField not working for non ObjectId primary keys

For instance if we have:

class Author(Document):
    name = StringField(min_length=2, primary_key=True)

And in a form if we use:

authors = DocumentMultipleChoiceField(queryset=Author.objects.all())

Then we get some ValidationError like "Shakespeare" is not a valid value for a primary key.

Create new object with an embedded form field

The parent_document requirement for embedded document inline formsets means that it's impossible to create a new object with embedded documents using the same form - there's simply no way to generate and save an embedded document inline formset unless that formset's parent_document already exists.

Am I missing something, or is this just not implemented?

"cannot import name format_html" if using Django 1.4

The latest update (0.2) seemed to add a reference to a util that doesn't exist in Django 1.4. With code that worked before I'm getting "cannot import name format_html" with the bottom of the trace having...

File "...\mongodbforms\widgets.py" in

  1. from django.utils.html import format_html

A quick Google showed django.utils.html only exists in Django 1.5 and above.

(edit)
Also I can't downgrade to 0.1.5 for some reason. Only 0.2 is listed for me both in PyCharm's list of available packages and on PyPi's webpage for mongodbforms.

'ValidationError' object has no attribute 'messages'

I'm trying to validate a constraint on a model using the models clean() method. Inside that method I'm throwing mongoengine.ValidationError(_('error message')).

This exception is being caught in the following lines of code:

        if hasattr(self.instance, 'clean'):
            try:
                self.instance.clean()
            except ValidationError as e:
                self._update_errors({NON_FIELD_ERRORS: e.messages})

However, e.messages doesn't exist and thus the below error is being thrown.

Any advice?

Cheers,
Andrew

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/staff/templates/edit/shoe-template/

Django Version: 1.5.2
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'gunicorn',
 'south',
 'djcelery',
 'mongodbforms',
 'bootstrapform',
 'post_office',
 'extra_views',
 'accounts',
 'staff',
 'project',
 'products',
 'debug_toolbar')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware')


Traceback:
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/core/handlers/base.py"
in get_response
  115.                         response = callback(request, *callback_args,
**callback_kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/views/generic/base.py"
in view
  68.             return self.dispatch(request, *args, **kwargs)
File "/Users/andrew/Projects/project/site/project/staff/views.py" in
dispatch
  127.             **kwargs
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/decorators.py"
in _wrapper
  25.             return bound_func(*args, **kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/contrib/auth/decorators.py"
in _wrapped_view
  25.                 return view_func(request, *args, **kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/decorators.py"
in bound_func
  21.                 return func(self, *args2, **kwargs2)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/decorators.py"
in _wrapper
  25.             return bound_func(*args, **kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/contrib/auth/decorators.py"
in _wrapped_view
  25.                 return view_func(request, *args, **kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/utils/decorators.py"
in bound_func
  21.                 return func(self, *args2, **kwargs2)
File "/Users/andrew/Projects/project/site/project/accounts/views.py"
in dispatch
  53.         return super(IsStaffMemberMixin, self).dispatch(request, *args,
**kwargs)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/views/generic/base.py"
in dispatch
  86.         return handler(request, *args, **kwargs)
File "/Users/andrew/Projects/project/site/project/staff/views.py" in
post
  142.         if form.is_valid():
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/forms/forms.py"
in is_valid
  126.         return self.is_bound and not bool(self.errors)
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/forms/forms.py"
in _get_errors
  117.             self.full_clean()
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/django/forms/forms.py"
in full_clean
  274.         self._post_clean()
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongodbforms/documents.py"
in _post_clean
  411.                 self._update_errors({NON_FIELD_ERRORS: e.messages})
File
"/Users/andrew/.virtualenvs/project/lib/python2.7/site-packages/mongoengine/errors.py"
in __getattribute__
  70.         message = super(ValidationError, self).__getattribute__(name)

Exception Type: AttributeError at /staff/templates/edit/shoe-template/
Exception Value: 'ValidationError' object has no attribute 'messages'

Python 3.X (?) : corrupted images in MapField

On my Python 3.3 machine images in a MapField of ImageFields can't be displayed, there're not considered as images. ImageFields outside a MapField are working and are well displayed.
Maybe there's something with the Python 3.X strings encoding (unicode by default, not binary) but I couldn't find where this could occur in the MapField code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.