Permalink
Browse files

Donate django-logicaldelete to Pinax

Patrick Altman donates django-logicaldelete to Pinax in the form of
creating the pinax-models package. He is doing this in order to:

1. Grow Pinax
2. Bring greater visibility and therefore better maintenance
opportunities to the project
  • Loading branch information...
paltman committed May 25, 2015
1 parent 4eb1533 commit b265879fe51448f00089c38e5cdd7fbdb46245ad
View
@@ -0,0 +1,7 @@
[run]
source = pinax
omit = pinax/models/tests/*,pinax/models/admin.py
branch = 1
[report]
omit = pinax/models/tests/*,pinax/models/admin.py
View
@@ -1 +1,10 @@
build
dist
.coverage
.tox
MANIFEST
*.pyc
*.egg-info
*.egg
docs/_build/
htmlcov/
View
@@ -0,0 +1,15 @@
language: python
python:
- "2.7"
- "3.3"
- "3.4"
env:
- DJANGO=1.7
- DJANGO=1.8
- DJANGO=master
install:
- pip install tox coveralls
script:
- tox -e py${TRAVIS_PYTHON_VERSION//[.]/}-$DJANGO
after_success:
- coveralls
View
@@ -1,2 +1,5 @@
Patrick Altman <paltman@gmail.com>
Matt George <mattgeorge@gmail.com>
Angel Velasquez <angvp@archlinux.org>
Cangiani Agustín <acangiani@routeatlas.com>
Jeff Bowen <jeff.d.bowen@gmail.com>
View
@@ -0,0 +1,161 @@
# How to Contribute
There are many ways you can help contribute to this project. Contributing
code, writing documentation, reporting bugs, as well as reading and providing
feedback on issues and pull requests, all are valid and necessary ways to
help.
## Committing Code
The great thing about using a distributed versioning control system like git
is that everyone becomes a committer. When other people write good patches
it makes it very easy to include their fixes/features and give them proper
credit for the work.
We recommend that you do all your work in a separate branch. When you
are ready to work on a bug or a new feature create yourself a new branch. The
reason why this is important is you can commit as often you like. When you are
ready you can merge in the change. Let's take a look at a common workflow:
git checkout -b task-566
... fix and git commit often ...
git push origin task-566
The reason we have created two new branches is to stay off of `master`.
Keeping master clean of only upstream changes makes yours and ours lives
easier. You can then send us a pull request for the fix/feature. Then we can
easily review it and merge it when ready.
### Writing Commit Messages
Writing a good commit message makes it simple for us to identify what your
commit does from a high-level. There are some basic guidelines we'd like to
ask you to follow.
A critical part is that you keep the **first** line as short and sweet
as possible. This line is important because when git shows commits and it has
limited space or a different formatting option is used the first line becomes
all someone might see. If your change isn't something non-trivial or there
reasoning behind the change is not obvious, then please write up an extended
message explaining the fix, your rationale, and anything else relevant for
someone else that might be reviewing the change. Lastly, if there is a
corresponding issue in Github issues for it, use the final line to provide
a message that will link the commit message to the issue and auto-close it
if appropriate.
Add ability to travel back in time
You need to be driving 88 miles per hour to generate 1.21 gigawatts of
power to properly use this feature.
Fixes #88
## Coding style
When writing code to be included in django-user-accounts keep our style in mind:
* Follow [PEP8](http://www.python.org/dev/peps/pep-0008/) there are some
cases where we do not follow PEP8. It is an excellent starting point.
* Follow [Django's coding style](http://docs.djangoproject.com/en/dev/internals/contributing/#coding-style)
we're pretty much in agreement on Django style outlined there.
We would like to enforce a few more strict guides not outlined by PEP8 or
Django's coding style:
* PEP8 tries to keep line length at 80 characters. We follow it when we can,
but not when it makes a line harder to read. It is okay to go a little bit
over 80 characters if not breaking the line improves readability.
* Use double quotes not single quotes. Single quotes are allowed in cases
where a double quote is needed in the string. This makes the code read
cleaner in those cases.
* Blank lines should contain no whitespace.
* Docstrings always use three double quotes on a line of their own, so, for
example, a single line docstring should take up three lines not one.
* Imports are grouped specifically and ordered alphabetically. This is shown
in the example below.
* Always use `reverse` and never `@models.permalink`.
* Tuples should be reserved for positional data structures and not used
where a list is more appropriate.
* URL patterns should use the `url()` function rather than a tuple.
Here is an example of these rules applied:
# first set of imports are stdlib imports
# non-from imports go first then from style import in their own group
import csv
# second set of imports are Django imports with contrib in their own
# group.
from django.core.urlresolvers import reverse
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
# third set of imports are external apps (if applicable)
from tagging.fields import TagField
# fourth set of imports are local apps
from .fields import MarkupField
class Task(models.Model):
"""
A model for storing a task.
"""
creator = models.ForeignKey(User)
created = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(default=timezone.now)
objects = models.Manager()
class Meta:
verbose_name = _("task")
verbose_name_plural = _("tasks")
def __unicode__(self):
return self.summary
def save(self, **kwargs):
self.modified = datetime.now()
super(Task, self).save(**kwargs)
def get_absolute_url(self):
return reverse("task_detail", kwargs={"task_id": self.pk})
# custom methods
class TaskComment(models.Model):
# ... you get the point ...
pass
## Pull Requests
Please keep your pull requests focused on one specific thing only. If you
have a number of contributions to make, then please send seperate pull
requests. It is much easier on maintainers to receive small, well defined,
pull requests, than it is to have a single large one that batches up a
lot of unrelated commits.
If you ended up making multiple commits for one logical change, please
rebase into a single commit.
git rebase -i HEAD~10 # where 10 is the number of commits back you need
This will pop up an editor with your commits and some instructions you want
to squash commits down by replacing 'pick' with 's' to have it combined with
the commit before it. You can squash multiple ones at the same time.
When you save and exit the text editor where you were squashing commits, git
will squash them down and then present you with another editor with commit
messages. Choose the one to apply to the squashed commit (or write a new
one entirely.) Save and exit will complete the rebase. Use a forced push to
your fork.
git push -f
View
46 LICENSE
@@ -1,27 +1,19 @@
Copyright (c) 2010-2014 Patrick Altman
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Patrick Altman nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Copyright (c) 2012-2015 James Tauber and contributors
#
# 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.
View
@@ -1,2 +1,5 @@
include AUTHORS
include LICENSE
include README.rst
recursive-include pinax/models/static *
recursive-include pinax/models/templates *
View
@@ -0,0 +1,15 @@
all: init docs test
init:
python setup.py develop
pip install detox coverage mkdocs
test:
coverage erase
detox
coverage html
docs:
mkdocs build
.PHONY: docs
View
@@ -1,51 +1,81 @@
Django Logical Delete
=====================
Pinax Models
============
This is a small and simple app that I threw together to get some reuse out of
something I do in nearly every project and every model I create. It's too easy
for good data to get deleted and it be unrecoverable. It's also too easy to
fix this by overriding the model's delete() method and just flagging records
as deleted and then leveraging Django's Managers to override default behavior
so that logically deleted items are not returned in querysets.
.. image:: https://img.shields.io/travis/pinax/pinax-models.svg
:target: https://travis-ci.org/pinax/pinax-models
There are two exceptions however, that I have found useful to this rule.
.. image:: https://img.shields.io/coveralls/pinax/pinax-models.svg
:target: https://coveralls.io/r/pinax/pinax-models
#. In the admin I like to see everything with an indicator of whether or not
.. image:: https://img.shields.io/pypi/dm/pinax-models.svg
:target: https://pypi.python.org/pypi/pinax-models/
.. image:: https://img.shields.io/pypi/v/pinax-models.svg
:target: https://pypi.python.org/pypi/pinax-models/
.. image:: https://img.shields.io/badge/license-MIT-blue.svg
:target: https://pypi.python.org/pypi/pinax-models/
This is a small and simple app that Patrick Altman wrote to get some reuse out
of something he did in nearly every project and every model he created. It's
too easy for good data to get deleted and it be unrecoverable. It's also too
easy to fix this by overriding the model's delete() method and just flagging
records as deleted and then leveraging Django's managers to override default
behavior so that logically deleted items are not returned in querysets.
There are two exceptions to this rule, however, that are useful.
#. In the admin it is nice to see everything with an indicator of whether or not
it has been deleted, with the ability to filter down to just active records,
(or deleted for that matter).
#. I still think it is a valid request when an item is fetched for by it's
primary key value, that the object should return, even if it is marked as
deleted.
#. It is a valid request when an item is fetched by its primary key value, that
the object should return, even if it is marked as deleted.
On May 25, 2015, Patrick donated `django-logicaldelete` to Pinax and as part of
that process, `pinax-models` was born and the code incorporated into that
package. It remains just a Django app and can be quite independently of other
Pinax apps.
To learn more about Pinax, see http://pinaxproject.com/
Installing django-logicaldelete
-------------------------------
Installing pinax-models
-----------------------
::
pip install django-logicaldelete
pip install django-models
Using django-logicaldelete
--------------------------
Using pinax-models
------------------
Using the app is pretty simple:
#. add `logicaldelete` to your INSTALLED_APPS
#. Inherit from `logicaldelete.models.Model` for all models that you wish to
share in this functionality.
#. Create and/or Register admins for each of these models using `logicaldelete.admin.ModelAdmin`
#. add `pinax.models` to your INSTALLED_APPS
#. Inherit from `pinax.models.LogicalDeleteModel` for all models that you wish
to share in this functionality.
#. Create and/or Register admins for each of these models using
`pinax.models.LogicalDeleteModelAdmin`
Additional
----------
Logical deletes are handled by date stamping a `date_removed` column. In addition, a `date_created` and `date_modified` columns will be populated as a convenience.
Logical deletes are handled by date stamping a `date_removed` column. In
addition, a `date_created` and `date_modified` columns will be populated as a
convenience.
Backwards Incompatible Changes
------------------------------
2.0
***
* Renamed to `pinax-models` and base model renamed to `LogicalDeleteModel`
1.1
***
Oops, something went wrong.

0 comments on commit b265879

Please sign in to comment.