hmarr/mongoengine — Issue #404: .append() to a ListField(ReferenceField()) silently fails under very specific circumstances - Test case
Author: djziegler
Created: 2012-01-05 16:35:58+00:00
State: open

```python

"""
Demonstrate a somewhat obscure bug with ListField(ReferenceField()).

1) Create an object with an empty ListField(ReferenceField()).
- the field can either be left empty (using the default value),
or you can explicity set it to empty.
- issue does not occur with ListField(StringField())
- if an object is appended now (before first persist) problem does not occur.
2) Save the object and reload it.
3) Append an entity to the ListField(ReferenceField()).
- the object will be silently dropped.
- setting the field to a list containing the item is a workaround.
- if an object had been added to the list in step 1, adding the
second object now would be fine.
"""

from mongoengine import *
import sys

class Dog(Document):
name = StringField ()
puppies = ListField(ReferenceField('Dog'))

def test ():

connect ('testdb')

Dog.drop_collection ()

# Create dog with empty puppies list
rover0 = Dog (name='Rover')

# Turning this on does not fix the problem
if False:
rover0.puppies = []

# If you turn this on, both this case, and the after-reload case will work fine.
if False:
puppy0 = Dog (name='puppy0')
puppy0.save ()
rover0.puppies.append (puppy0)
print 'Added a puppy before initial save', [p.name for p in rover0.puppies]

# Save the dog
rover0.save ()

# Load the same dog again
rover1 = Dog.objects(name='Rover').get ()

# Create and persist a puppy
puppy1 = Dog (name='puppy1')
puppy1.save ()

# Turning this on does not fix the problem
if False:
rover1.puppies = []

# Append the puppy to the puppies list
rover1.puppies.append (puppy1)
if puppy1 not in rover1.puppies:
print '*** Whoops: puppy did not get appended:', [p.name for p in rover1.puppies]

# This works however
rover1.puppies = rover1.puppies + [puppy1]
print 'Using workaround, all is good:', [p.name for p in rover1.puppies]

if __name__ == '__main__':
test ()

```