Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#24690 closed Cleanup/optimization (fixed)

Warn about mutable defaults with ArrayField

Reported by: Bryan Rehbein Owned by: MZ
Component: Documentation Version: 1.8
Severity: Normal Keywords: ArrayField postgres
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I found an issue when upgrading to Django 1.8 and using the new ArrayField and a model's instance methods.

This code will cause Model#array_field's data to bleed between different instances.

def add_to_array(self, item):
    if item not in self.array_field:
        self.array_field.append(item)

However, this code does the correct thing:

def add_to_array(self, item):
    existing = self.array_field

    if item not in self.array_field:
        self.array_field = existing + [item]

I put together a django project/app with the code and tests that show the problems with self.array_field.append(). It also has a Vagrant file setup that should also exhibit the problems.

https://github.com/redbeard0x0a/django18bug

Change History (11)

comment:1 by Tim Graham, 9 years ago

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

comment:2 by Marc Tamlyn, 9 years ago

Resolution: worksforme
Status: newclosed

The issue in your example code is that you have used default=[]. This default is shared between all instances and in this case it is mutable, so you are modifying the default array.

The correct code is to use default=list.

I don't consider this a bug in Django - this is the same behaviour as you would get if you have code like:

def myfunc(foo, bar=[]):
    bar.append(foo)
    return bar

The first call to myfunc(1) would return [1], the second [1, 1], etc.

comment:3 by Tim Graham, 9 years ago

Component: contrib.postgresDocumentation
Owner: set to nobody
Resolution: worksforme
Severity: Release blockerNormal
Status: closednew
Summary: ArrayField data bleeds between instances when using field.append(item)Warn about mutable defaults with ArrayField
Type: BugCleanup/optimization

Could we add a warning about mutable defaults to the ArrayField docs? I guess this also applies to JSONField.

comment:4 by MZ, 9 years ago

Owner: changed from nobody to MZ
Status: newassigned

comment:5 by MZ, 9 years ago

Has patch: set

comment:6 by Tim Graham, 9 years ago

Patch needs improvement: set

comment:7 by Tim Graham, 9 years ago

Patch needs improvement: unset

comment:8 by Tim Graham, 9 years ago

Patch needs improvement: set

comment:9 by Tim Graham, 9 years ago

Patch needs improvement: unset

comment:10 by Tim Graham <timograham@…>, 9 years ago

Resolution: fixed
Status: assignedclosed

In f93e7f5:

Fixed #24690 -- Added a warning about mutable defaults for ArrayField/JSONField.

comment:11 by Tim Graham <timograham@…>, 9 years ago

In ef5cf564:

[1.8.x] Fixed #24690 -- Added a warning about mutable defaults for ArrayField.

Backport of f93e7f5674436b230e6b4023570939a20c0c6055 from master

Note: See TracTickets for help on using tickets.
Back to Top