mirror of
https://github.com/django/django.git
synced 2025-06-05 03:29:12 +00:00
Some event use. Slight manipulator refactor.
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1715 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4e25fec9f4
commit
dbd3869610
@ -201,7 +201,7 @@ auto_populated_field_script = register.simple_tag(auto_populated_field_script)
|
|||||||
#@register.simple_tag
|
#@register.simple_tag
|
||||||
def filter_interface_script_maybe(bound_field):
|
def filter_interface_script_maybe(bound_field):
|
||||||
f = bound_field.field
|
f = bound_field.field
|
||||||
if f.rel and isinstance(f.rel, meta.ManyToMany) and f.rel.filter_interface:
|
if f.rel and isinstance(f.rel, models.ManyToMany) and f.rel.filter_interface:
|
||||||
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
|
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
|
||||||
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
|
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
|
||||||
f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)
|
f.name, f.verbose_name, f.rel.filter_interface-1, ADMIN_MEDIA_PREFIX)
|
||||||
|
@ -16,6 +16,7 @@ from django.db.models.fields.related import *
|
|||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db.models.exceptions import FieldDoesNotExist, BadKeywordArguments
|
from django.db.models.exceptions import FieldDoesNotExist, BadKeywordArguments
|
||||||
|
from django.db.models.signals import Signals
|
||||||
|
|
||||||
# Admin stages.
|
# Admin stages.
|
||||||
ADD, CHANGE, BOTH = 1, 2, 3
|
ADD, CHANGE, BOTH = 1, 2, 3
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
from django.db.models.manipulators import ManipulatorDescriptor, ModelAddManipulator, ModelChangeManipulator
|
from django.db.models.manipulators import ModelAddManipulator, ModelChangeManipulator
|
||||||
from django.db.models.fields import Field, DateField, FileField, ImageField, AutoField
|
from django.db.models.fields import AutoField
|
||||||
from django.db.models.fields.related import RelatedField, OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT
|
from django.db.models.fields.related import OneToOne, ManyToOne
|
||||||
from django.db.models.related import RelatedObject
|
from django.db.models.related import RelatedObject
|
||||||
from django.db.models.manager import Manager, ManagerDescriptor
|
from django.db.models.manager import Manager
|
||||||
from django.db.models.query import orderlist2sql
|
from django.db.models.query import orderlist2sql
|
||||||
from django.db.models.options import Options
|
from django.db.models.options import Options
|
||||||
from django.db import connection, backend
|
from django.db import connection, backend
|
||||||
|
from django.db.models.signals import Signals
|
||||||
|
|
||||||
|
from django.dispatch import dispatcher
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
|
|
||||||
@ -25,6 +27,7 @@ get_module_name = lambda class_name: class_name.lower() + 's'
|
|||||||
get_verbose_name = lambda class_name: re.sub('([A-Z])', ' \\1', class_name).lower().strip()
|
get_verbose_name = lambda class_name: re.sub('([A-Z])', ' \\1', class_name).lower().strip()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ModelBase(type):
|
class ModelBase(type):
|
||||||
"Metaclass for all models"
|
"Metaclass for all models"
|
||||||
def __new__(cls, name, bases, attrs):
|
def __new__(cls, name, bases, attrs):
|
||||||
@ -118,6 +121,9 @@ def cmp_cls(x, y):
|
|||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__metaclass__ = ModelBase
|
||||||
|
|
||||||
@ -128,9 +134,7 @@ class Model(object):
|
|||||||
setattr(cls, name, attribute)
|
setattr(cls, name, attribute)
|
||||||
add_to_class = classmethod(add_to_class)
|
add_to_class = classmethod(add_to_class)
|
||||||
|
|
||||||
AddManipulator = ManipulatorDescriptor('AddManipulator', ModelAddManipulator)
|
|
||||||
ChangeManipulator = ManipulatorDescriptor('ChangeManipulator', ModelChangeManipulator)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s object>' % self.__class__.__name__
|
return '<%s object>' % self.__class__.__name__
|
||||||
|
|
||||||
@ -141,6 +145,7 @@ class Model(object):
|
|||||||
return not self.__eq__(other)
|
return not self.__eq__(other)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
dispatcher.send( signal = Signals.pre_init, sender = self.__class__, args=args, kwargs=kwargs)
|
||||||
if kwargs:
|
if kwargs:
|
||||||
for f in self._meta.fields:
|
for f in self._meta.fields:
|
||||||
if isinstance(f.rel, ManyToOne):
|
if isinstance(f.rel, ManyToOne):
|
||||||
@ -171,15 +176,21 @@ class Model(object):
|
|||||||
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
||||||
for i, arg in enumerate(args):
|
for i, arg in enumerate(args):
|
||||||
setattr(self, self._meta.fields[i].attname, arg)
|
setattr(self, self._meta.fields[i].attname, arg)
|
||||||
|
dispatcher.send( signal = Signals.post_init, sender = self.__class__, instance=self)
|
||||||
|
|
||||||
def _prepare(cls):
|
def _prepare(cls):
|
||||||
|
cls.add_to_class( 'AddManipulator', ModelAddManipulator)
|
||||||
|
cls.add_to_class( 'ChangeManipulator', ModelChangeManipulator)
|
||||||
|
|
||||||
# Creates some methods once self._meta has been populated.
|
# Creates some methods once self._meta has been populated.
|
||||||
|
|
||||||
if cls._meta.order_with_respect_to:
|
if cls._meta.order_with_respect_to:
|
||||||
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
|
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
|
||||||
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
|
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
|
||||||
|
|
||||||
RelatedField.do_pending_lookups(cls)
|
dispatcher.send( signal = Signals.class_prepared, sender = cls)
|
||||||
|
|
||||||
|
#RelatedField.do_pending_lookups(cls)
|
||||||
|
|
||||||
_prepare = classmethod(_prepare)
|
_prepare = classmethod(_prepare)
|
||||||
|
|
||||||
@ -187,6 +198,7 @@ class Model(object):
|
|||||||
# Run any pre-save hooks.
|
# Run any pre-save hooks.
|
||||||
if hasattr(self, '_pre_save'):
|
if hasattr(self, '_pre_save'):
|
||||||
self._pre_save()
|
self._pre_save()
|
||||||
|
dispatcher.send( signal=Signals.pre_save, sender = self.__class__, instance = self )
|
||||||
|
|
||||||
non_pks = [f for f in self._meta.fields if not f.primary_key]
|
non_pks = [f for f in self._meta.fields if not f.primary_key]
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
@ -231,6 +243,8 @@ class Model(object):
|
|||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
# Run any post-save hooks.
|
# Run any post-save hooks.
|
||||||
|
dispatcher.send(signal=Signals.pre_save, sender = self.__class__, instance = self )
|
||||||
|
|
||||||
if hasattr(self, '_post_save'):
|
if hasattr(self, '_post_save'):
|
||||||
self._post_save()
|
self._post_save()
|
||||||
|
|
||||||
@ -283,6 +297,8 @@ class Model(object):
|
|||||||
# Run any pre-delete hooks.
|
# Run any pre-delete hooks.
|
||||||
if hasattr(instance, '_pre_delete'):
|
if hasattr(instance, '_pre_delete'):
|
||||||
instance._pre_delete()
|
instance._pre_delete()
|
||||||
|
|
||||||
|
dispatcher.send(signal=Signals.pre_delete, sender = cls, instance = instance )
|
||||||
|
|
||||||
for related in cls._meta.get_all_related_many_to_many_objects():
|
for related in cls._meta.get_all_related_many_to_many_objects():
|
||||||
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
|
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
|
||||||
@ -311,14 +327,9 @@ class Model(object):
|
|||||||
[pk_val])
|
[pk_val])
|
||||||
|
|
||||||
setattr(self, cls._meta.pk.attname, None)
|
setattr(self, cls._meta.pk.attname, None)
|
||||||
for f in cls._meta.fields:
|
|
||||||
if isinstance(f, FileField) and getattr(self, f.attname):
|
dispatcher.send(signal=Signals.post_delete, sender = cls, instance = instance )
|
||||||
file_name = getattr(instance, 'get_%s_filename' % f.name)()
|
|
||||||
# If the file exists and no other object of this type references it,
|
|
||||||
# delete it from the filesystem.
|
|
||||||
if os.path.exists(file_name) and not cls._default_manager.get_list(**{'%s__exact' % f.name: getattr(self, f.name)}):
|
|
||||||
os.remove(file_name)
|
|
||||||
# Run any post-delete hooks.
|
|
||||||
if hasattr(instance, '_post_delete'):
|
if hasattr(instance, '_post_delete'):
|
||||||
instance._post_delete()
|
instance._post_delete()
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from django.db.models.signals import Signals
|
||||||
|
from django.dispatch import dispatcher
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import formfields, validators
|
from django.core import formfields, validators
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
@ -6,6 +8,7 @@ from django.utils.text import capfirst
|
|||||||
from django.utils.translation import gettext_lazy, ngettext
|
from django.utils.translation import gettext_lazy, ngettext
|
||||||
import datetime, os
|
import datetime, os
|
||||||
|
|
||||||
|
|
||||||
# Random entropy string used by "default" param.
|
# Random entropy string used by "default" param.
|
||||||
NOT_PROVIDED = 'oijpwojefiojpanv'
|
NOT_PROVIDED = 'oijpwojefiojpanv'
|
||||||
|
|
||||||
@ -502,6 +505,20 @@ class FileField(Field):
|
|||||||
setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))
|
setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))
|
||||||
setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))
|
setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))
|
||||||
setattr(cls, 'save_%s_file' % self.name, curry(cls._save_FIELD_file, field=self))
|
setattr(cls, 'save_%s_file' % self.name, curry(cls._save_FIELD_file, field=self))
|
||||||
|
dispatcher.connect(
|
||||||
|
self.delete_file,
|
||||||
|
signal = Signals.post_delete,
|
||||||
|
sender = cls
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_file(self, instance):
|
||||||
|
if getattr(instance, f.attname):
|
||||||
|
file_name = getattr(instance, 'get_%s_filename' % f.name)()
|
||||||
|
# If the file exists and no other object of this type references it,
|
||||||
|
# delete it from the filesystem.
|
||||||
|
if os.path.exists(file_name) and \
|
||||||
|
not instance.__class__._default_manager.get_list(**{'%s__exact' % self.name: getattr(instance, self.attname)}):
|
||||||
|
os.remove(file_name)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [formfields.FileUploadField, formfields.HiddenField]
|
return [formfields.FileUploadField, formfields.HiddenField]
|
||||||
|
@ -3,7 +3,9 @@ from django.db.models.related import RelatedObject
|
|||||||
from django.utils.translation import gettext_lazy, string_concat
|
from django.utils.translation import gettext_lazy, string_concat
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
from django.core import formfields
|
from django.core import formfields
|
||||||
|
from django.db.models.signals import Signals
|
||||||
|
|
||||||
|
from django.dispatch import dispatcher
|
||||||
|
|
||||||
# Values for Relation.edit_inline.
|
# Values for Relation.edit_inline.
|
||||||
TABULAR, STACKED = 1, 2
|
TABULAR, STACKED = 1, 2
|
||||||
@ -14,6 +16,12 @@ RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
|
|||||||
class RelatedField(object):
|
class RelatedField(object):
|
||||||
pending_lookups = {}
|
pending_lookups = {}
|
||||||
|
|
||||||
|
dispatcher.connect(
|
||||||
|
lambda sender: RelatedField.do_pending_lookups(sender) ,
|
||||||
|
signal = Signals.class_prepared,
|
||||||
|
weak = False)
|
||||||
|
|
||||||
|
|
||||||
def add_lookup(cls, rel_cls, field):
|
def add_lookup(cls, rel_cls, field):
|
||||||
name = field.rel.to
|
name = field.rel.to
|
||||||
module = rel_cls.__module__
|
module = rel_cls.__module__
|
||||||
@ -28,6 +36,8 @@ class RelatedField(object):
|
|||||||
field.do_related_class(other_cls, rel_cls)
|
field.do_related_class(other_cls, rel_cls)
|
||||||
do_pending_lookups = classmethod(do_pending_lookups)
|
do_pending_lookups = classmethod(do_pending_lookups)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name):
|
def contribute_to_class(self, cls, name):
|
||||||
Field.contribute_to_class(self,cls,name)
|
Field.contribute_to_class(self,cls,name)
|
||||||
other = self.rel.to
|
other = self.rel.to
|
||||||
|
@ -15,11 +15,14 @@ class ManipulatorDescriptor(object):
|
|||||||
if instance != None:
|
if instance != None:
|
||||||
raise "Manipulator accessed via instance"
|
raise "Manipulator accessed via instance"
|
||||||
else:
|
else:
|
||||||
class Man(self.get_base_manipulator(type), self.base):
|
if not self.man:
|
||||||
pass
|
class Man(self.get_base_manipulator(type), self.base):
|
||||||
Man.classinit(type)
|
pass
|
||||||
Man.__name__ = self.name
|
|
||||||
return Man
|
Man._prepare(type)
|
||||||
|
Man.__name__ = self.name
|
||||||
|
self.man = Man
|
||||||
|
return self.man
|
||||||
|
|
||||||
def get_base_manipulator(self, type):
|
def get_base_manipulator(self, type):
|
||||||
if hasattr(type, 'MANIPULATOR'):
|
if hasattr(type, 'MANIPULATOR'):
|
||||||
@ -30,7 +33,7 @@ class ManipulatorDescriptor(object):
|
|||||||
|
|
||||||
|
|
||||||
class AutomaticManipulator(Manipulator):
|
class AutomaticManipulator(Manipulator):
|
||||||
def classinit(cls, model):
|
def _prepare(cls, model):
|
||||||
cls.model = model
|
cls.model = model
|
||||||
cls.manager = model._default_manager
|
cls.manager = model._default_manager
|
||||||
cls.opts = model._meta
|
cls.opts = model._meta
|
||||||
@ -43,7 +46,11 @@ class AutomaticManipulator(Manipulator):
|
|||||||
setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_month), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_month), opts, 'month'))
|
setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_month), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_month), opts, 'month'))
|
||||||
if f.unique_for_year:
|
if f.unique_for_year:
|
||||||
setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_year), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_year), opts, 'year'))
|
setattr(cls, 'isUnique%sFor%s' % (f.name, f.unique_for_year), curry(manipulator_validator_unique_for_date, f, opts.get_field(f.unique_for_year), opts, 'year'))
|
||||||
classinit = classmethod(classinit)
|
_prepare = classmethod(_prepare)
|
||||||
|
|
||||||
|
def contribute_to_class(cls, other_cls, name ):
|
||||||
|
setattr(other_cls, name, ManipulatorDescriptor(name, cls))
|
||||||
|
contribute_to_class = classmethod(contribute_to_class)
|
||||||
|
|
||||||
def __init__(self, original_object= None, follow=None):
|
def __init__(self, original_object= None, follow=None):
|
||||||
self.follow = self.model._meta.get_follow(follow)
|
self.follow = self.model._meta.get_follow(follow)
|
||||||
|
11
django/db/models/signals.py
Normal file
11
django/db/models/signals.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Signals(object):
|
||||||
|
class_prepared = object()
|
||||||
|
|
||||||
|
pre_init= object()
|
||||||
|
post_init = object()
|
||||||
|
|
||||||
|
pre_save = object()
|
||||||
|
post_save = object()
|
||||||
|
|
||||||
|
pre_delete = object()
|
||||||
|
post_delete = object()
|
@ -27,7 +27,7 @@ Internal attributes:
|
|||||||
"""
|
"""
|
||||||
from __future__ import generators
|
from __future__ import generators
|
||||||
import types, weakref
|
import types, weakref
|
||||||
from dispatch import saferef, robustapply, errors
|
from django.dispatch import saferef, robustapply, errors
|
||||||
|
|
||||||
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
__cvsid__ = "$Id: dispatcher.py,v 1.8 2004/11/26 06:37:33 mcfletch Exp $"
|
__cvsid__ = "$Id: dispatcher.py,v 1.8 2004/11/26 06:37:33 mcfletch Exp $"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user