Skip to content

calling append() on a ListField changes the default value #50

Open
@lingthio

Description

@lingthio

Thanks for this great package!

On object creation, where:

  • an attribute's Field.default has been defined, and
  • an attribute value is not specified in **kwargs

the object is created with this attribute value set to the Field.default.

For ListField attributes, this causes a problem, because list operations such as
append() will modify the Field.default and subsequent object creations will
behave unexpectedly.

I have included a code illustration below.

The obvious fix is to always initialize an object with a COPY of the Field.default.

from flask import Flask
from flask_mongoalchemy import MongoAlchemy

# Setup Flask
app = Flask(__name__)

# Setup MongoAlchemy
app.config.update(MONGOALCHEMY_DATABASE='issue_db')
db = MongoAlchemy(app)

# Define Item Document
class Item(db.Document):
    name = db.StringField(default='')
    colors = db.ListField(db.StringField(), default=[])

# Clear Item collection
db.session.clear_collection(Item)

# Create Documents
item1 = Item(name='Item One')
db.session.add(item1)
# item1.colors.append() modifies the Field default
item1.colors.append('red')
item1.colors.append('blue')

item2 = Item(name='Item Two')
db.session.add(item2)
db.session.flush()

# item2 is created with the modified Field default
assert item2.colors==[], 'item2.colors='+str(item2.colors)+' instead of []'

If users are looking for a temporary workaround:

item1.colors = item1.colors + ['red']  # this ensures a copy is assigned
item1.colors = item1.colors + ['blue']  # this ensures a copy is assigned

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions