__all__ = (
from django.db.models.base import ModelBase
from django.db.models.options import Options
"""Return a model metaclass that ensures a certain field order, as
specified by ``requests``. This is useful in inheritance scenarios,
where the order cannot be controlled declaratively.
__metaclass__ = set_field_order(('name', 'aliases',))
``requests`` is expected to be tuple of field names, or an iterable of
Ultimately, the model field order should be irrelevant and the form
system might be a better place to do this. Generic admin appliations
should approach this as newforms-admin does, registering this sort
of information with the application by way of a custom class, or
something similar. Once newforms-admin lands, applications uses this
should probably consider switching to using the same config data as
if not requests:
# support simplified syntax for single sort requests
if not isinstance(requests, (list,tuple)):
requests = (requests,)
cache = list(self._field_cache)
for i in range(0, len(cache)):
if cache[i].name == name:
# handle each sort request in order
for request in requests:
anchor_idx = None
for field_name in request:
field_idx = idx(field_name)
if field_idx is None:
raise ValueError('Invalid field name "%s"'%field_name)
# first field in the request is the anchor, all the
# other fields will be inserted after it.
if anchor_idx is None:
anchor_idx = field_idx
field = cache[field_idx]
if field_idx > anchor_idx:
anchor_idx += 1
# already initialized by parent; override with our new
# data now, with the correct sort order.
self._field_cache = cache
self._field_name_cache = [x for x, _ in cache]
def __new__(cls, name, bases, attrs):
model = super(OrderMetaclass, cls).__new__(cls, name, bases, attrs)
model._meta.__class__ = OrderedOptions
model._meta._fill_fields_cache() # already filled, regen
from django.db.models import AutoField
"""Create a copy of a model instance.
Works in model inheritance case where ``instance.pk = None`` is
not good enough, since the subclass instance refers to the
parent_link's primary key during save.
M2M relationships are currently not handled, i.e. they are not
See also Django #4027.
initial = dict([(f.name, getattr(obj, f.name))
for f in obj._meta.fields
if not isinstance(f, AutoField) and\
not f in obj._meta.parents.values()])
from django.db.models.deletion import Collector
from django.db import router
def has_related_objects(obj, ignore=):
"""Returns ``True`` if the model instance ``obj`` has any related
objects depending on it.
This allows you to check, for example, whether a delete would be
cascading, i.e. cause other objects to be deleted, too.
You may pass a list of model classes in ``ignore`` - dependencies
from those models will then not be considered.
With respect to model inheritance, parent model records will be
ignored, while subclass model will count. For example, say ``B``
inherits ``A``. Now, when deleting ``b``, ``a`` would not be
considered a related object by this function. However, when
deleting ``a``, ``b`` would.
# TODO: untested with multi-level inheritance, multiple parents
# TODO: add tests
model = type(obj)
collector = Collector(using=router.db_for_write(model))
for so_klass, items in collector.data.items():
# Make sure there are instances for this relation.
if not len(items):
# Auto-created m2m models we don't care about. The admin ignores
# those in it's ``django.contrib.admin.util.NestedObjects`` class.
# Also ignore any subclasses (in case of inheritance).
if issubclass(so_klass, model):
# Does the user explicitely ask us to ignore this model?
if so_klass in ignore:
# -> So there is at least one related object that counts