Skip to content

Commit

Permalink
Merge pull request #1 from wesleykendall/develop
Browse files Browse the repository at this point in the history
First version of django manager utils
  • Loading branch information
wesleykendall committed Mar 6, 2014
2 parents 60b288d + 50cccd4 commit 06c4b07
Show file tree
Hide file tree
Showing 16 changed files with 914 additions and 14 deletions.
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Compiled python files
*.pyc

# Vim files
*.swp
*.swo

# Coverage files
.coverage

# Setuptools distribution folder.
/dist/

# Python egg metadata, regenerated from source files by setuptools.
/*.egg-info
/*.egg
15 changes: 15 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
language: python
python:
- '2.7'
env:
- DJANGO=1.6.1 DB=postgres
install:
- pip install -q Django==$DJANGO
- pip install -r requirements.txt
before_script:
- find . | grep .py$ | grep -v /migrations | xargs pep8 --max-line-length=120
- find . | grep .py$ | grep -v /migrations | grep -v __init__.py | xargs pyflakes
- psql -c 'CREATE DATABASE manager_utils;' -U postgres
script:
- coverage run --source='manager_utils' --branch manage.py test
- coverage report --fail-under=100
23 changes: 11 additions & 12 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ The MIT License (MIT)

Copyright (c) 2014 Ambition

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include manager_utils/VERSION
include README.md
include LICENSE
134 changes: 132 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,134 @@
[![Build Status](https://travis-ci.org/ambitioninc/django-manager-utils.png)](https://travis-ci.org/ambitioninc/django-manager-utils)
django-manager-utils
====================
=====================

Model manager utils for Django
Additional utilities for Django model managers.

## A Brief Overview
Django manager utils allows a user to perform various functions not natively supported by Django's model managers. To use the manager in your Django models, do:

from manager_utils import ManagerUtilsManager

class MyModel(Model):
objects = ManagerUtilsManager()

If you want to extend an existing manager to use the manager utils, include mixin provided first (since it overrides the get_queryset function) as follows:

from manager_utils import ManagerUtilsMixin

class MyManager(ManagerUtilsMixin, Manager):
pass

An overview of each util is below with links to more in-depth documentation and examples for each function.

- [single](#single): Grabs a single element from table and verifies it is the only element.
- [get_or_none](#get_or_none): Performs a get on a queryset and returns None if the object does not exist.
- [upsert](#upsert): Performs an upsert (update or insert) to a model.
- [bulk_update](#bulk_update): Bulk updates a list of models and the fields that have been updated.


## single()<a name="single"></a>
Assumes that the model only has one element in the table or queryset and returns that value. If the table has more than one or no value, an exception is raised.

**Returns**: The only model object in the queryset.

**Raises**: DoesNotExist error when the object does not exist or a MultipleObjectsReturned error when there is more than one object.

**Examples**:

TestModel.objects.create(int_field=1)
model_obj = TestModel.objects.single()
print model_obj.int_field
1

## get_or_none(\*\*query_params)<a name="get_or_none"></a>
Get an object or return None if it doesn't exist.

**Args**:
- \*\*query_params: The query parameters used in the lookup.

**Returns**: A model object if one exists with the query params, None otherwise.

**Examples**:

model_obj = TestModel.objects.get_or_none(int_field=1)
print model_obj
None

TestModel.objects.create(int_field=1)
model_obj = TestModel.objects.get_or_none(int_field=1)
print model_obj.int_field
1

## upsert(defaults=None, updates=None, \*\*kwargs)<a name="upsert"></a>
Performs an update on an object or an insert if the object does not exist.

**Args**:
- defaults: These values are set when the object is inserted, but are irrelevant when the object already exists. This field should only be used when values only need to be set during creation.
- updates: These values are updated when the object is updated. They also override any values provided in the defaults when inserting the object.
- \*\*kwargs: These values provide the arguments used when checking for the existence of the object. They are used in a similar manner to Django's get_or_create function and are set in a created object.

**Returns**: A tuple of the upserted object and a Boolean that is True if it was created (False otherwise)

**Examples**:

# Upsert a test model with an int value of 1. Use default values that will be given to it when created
model_obj, created = TestModel.objects.upsert(int_field=1, defaults={'float_field': 2.0})
print created
True
print model_obj.int_field, model_obj.float_field
1, 2.0

# Do an upsert on that same model with different default fields. Since it already exists, the defaults
# are not used
model_obj, created = TestModel.objects.upsert(int_field=1, defaults={'float_field': 3.0})
print created
False
print model_obj.int_field, model_obj.float_field
1, 2.0

# In order to update the float field in an existing object, use the updates dictionary
model_obj, created = TestModel.objects.upsert(int_field=1, updates={'float_field': 3.0})
print created
False
print model_obj.int_field, model_obj.float_field
1, 3.0

# You can use updates on a newly created object that will also be used as initial values.
model_obj, created = TestModel.objects.upsert(int_field=2, updates={'float_field': 4.0})
print created
True
print model_obj.int_field, model_obj.float_field
2, 4.0

## bulk_update(model_objs, fields_to_update)<a name="bulk_update"></a>
Performs an bulk update on an list of objects. Any fields listed in the fields_to_update array will be updated in the database.

**Args**:
- model_objs: A list of model objects that are already stored in the database.
- fields_to_update: A list of fields to update in the models. Only these fields will be updated in the database. The 'id' field is included by default.

**Examples**:

# Create a couple test models
model_obj1 = TestModel.objects.create(int_field=1, float_field=2.0, char_field='Hi')
model_obj2 = TestModel.objects.create(int_field=3, float_field=4.0, char_field='Hello')

# Change their fields and do a bulk update
model_obj1.int_field = 10
model_obj1.float_field = 20.0
model_obj2.int_field = 30
model_obj2.float_field = 40.0
TestModel.objects.bulk_update([model_obj1, model_obj2], ['int_field', 'float_field'])

# Reload the models and view their changes
model_obj1 = TestModel.objects.get(id=model_obj1.id)
print model_obj1.int_field, model_obj1.float_field
10, 20.0

model_obj2 = TestModel.objects.get(id=model_obj2.id)
print model_obj2.int_field, model_obj2.float_field
10, 20.0

## License
MIT License (See the LICENSE file included in this repository)
10 changes: 10 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env python
import os
import sys

if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'test_project.settings')

from django.core.management import execute_from_command_line

execute_from_command_line(sys.argv)
1 change: 1 addition & 0 deletions manager_utils/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.1
1 change: 1 addition & 0 deletions manager_utils/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .manager_utils import ManagerUtilsMixin, ManagerUtilsManager
Loading

0 comments on commit 06c4b07

Please sign in to comment.