Skip to content

Commit

Permalink
Add support for update_or_create
Browse files Browse the repository at this point in the history
  • Loading branch information
rbusquet authored and stphivos committed Mar 21, 2018
1 parent e3bdbda commit 751d8d2
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ dist/
MANIFEST
patches.py
db.sqlite3
.python-version
18 changes: 18 additions & 0 deletions django_mock_queries/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,24 @@ def get_or_create(self, defaults=None, **attrs):
else:
return results[0], False

def update_or_create(self, defaults=None, **attrs):
if defaults is not None:
validate_mock_set(self)
defaults = defaults or {}
lookup = attrs.copy()
attrs.update(defaults)
results = self.filter(**lookup)
if not results.exists():
return self.create(**attrs), True
elif results.count() > 1:
raise MultipleObjectsReturned()
else:
obj = results[0]
for k, v in attrs.items():
setattr(obj, k, v)
self.fire(obj, self.EVENT_UPDATED, self.EVENT_SAVED)
return obj, False

def _item_values(self, item, fields):
field_buckets = {}
result_count = 1
Expand Down
100 changes: 100 additions & 0 deletions tests/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,106 @@ def test_query_get_or_create_raises_model_not_specified_with_defaults_when_mocks
with self.assertRaises(ModelNotSpecified):
qs.get_or_create(defaults={'first': 3, 'third': 2}, second=1)

def test_query_update_or_create_gets_existing_unique_match(self):
item_1 = MockModel(foo=1)
item_2 = MockModel(foo=2)
item_3 = MockModel(foo=3)

self.mock_set.add(item_1, item_2, item_3)
obj, created = self.mock_set.update_or_create(foo=2)

assert obj == item_2
assert created is False

def test_query_update_or_create_raises_does_multiple_objects_returned_when_more_than_one_match(self):
item_1 = MockModel(foo=1)
item_2 = MockModel(foo=1)
item_3 = MockModel(foo=2)

self.mock_set.add(item_1, item_2, item_3)
self.assertRaises(MultipleObjectsReturned, self.mock_set.update_or_create, foo=1)

def test_query_update_or_create_creates_new_model_when_no_match(self):
item_1 = MockModel(foo=1)
item_2 = MockModel(foo=2)
item_3 = MockModel(foo=3)

qs = MockSet(model=create_model('foo'))
qs.add(item_1, item_2, item_3)
obj, created = qs.update_or_create(foo=4)

assert hasattr(obj, 'foo') and obj.foo == 4
assert created is True

def test_query_update_or_create_gets_existing_unique_match_with_defaults(self):
qs = MockSet(
model=create_model('first', 'second', 'third')
)
item_1 = MockModel(first=1)
item_2 = MockModel(second=2)
item_3 = MockModel(third=3)
qs.add(item_1, item_2, item_3)

obj, created = qs.update_or_create(defaults={'first': 3, 'third': 1}, second=2)

assert hasattr(obj, 'second') and obj.second == 2
assert created is False

def test_query_update_or_create_raises_does_multiple_objects_returned_when_more_than_one_match_with_defaults(self):
qs = MockSet(
model=create_model('first', 'second', 'third')
)
item_1 = MockModel(first=1)
item_2 = MockModel(first=1)
item_3 = MockModel(third=3)
qs.add(item_1, item_2, item_3)

qs.add(item_1, item_2, item_3)
with self.assertRaises(MultipleObjectsReturned):
qs.update_or_create(first=1, defaults={'second': 2})

def test_query_update_or_create_creates_new_model_when_no_match_with_defaults(self):
qs = MockSet(
model=create_model('first', 'second', 'third')
)
item_1 = MockModel(first=1)
item_2 = MockModel(second=2)
item_3 = MockModel(third=3)
qs.add(item_1, item_2, item_3)

obj, created = qs.update_or_create(defaults={'first': 3}, second=1)

assert hasattr(obj, 'first') and obj.first == 3
assert hasattr(obj, 'second') and obj.second == 1
assert hasattr(obj, 'third') and obj.third is None
assert created is True

def test_query_update_or_create_updates_match_with_defaults(self):
qs = MockSet(
model=create_model('first', 'second', 'third')
)
item_1 = MockModel(first=1)
item_2 = MockModel(second=2)
item_3 = MockModel(third=3)
qs.add(item_1, item_2, item_3)

obj, created = qs.update_or_create(defaults={'first': 3, 'third': 1}, second=2)

assert hasattr(obj, 'first') and obj.first == 3
assert hasattr(obj, 'second') and obj.second == 2
assert hasattr(obj, 'third') and obj.third == 1
assert created is False

def test_query_update_or_create_raises_model_not_specified_with_defaults_when_mockset_model_is_none(self):
qs = MockSet()
item_1 = MockModel(first=1)
item_2 = MockModel(second=2)
item_3 = MockModel(third=3)
qs.add(item_1, item_2, item_3)

with self.assertRaises(ModelNotSpecified):
qs.update_or_create(defaults={'first': 3, 'third': 2}, second=1)

def test_query_return_self_methods_accept_any_parameters_and_return_instance(self):
qs = MockSet(MockModel(foo=1), MockModel(foo=2))
assert qs == qs.all()
Expand Down

0 comments on commit 751d8d2

Please sign in to comment.