рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, django рдПрдХ рдмрд╣реБрдд рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдФрд░ рд▓рдЪреАрд▓рд╛ рдврд╛рдВрдЪрд╛ рд╣реИред рдЙрд╕рдХреЗ рд▓рд┐рдП рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдП рдЧрдП рд╣реИрдВ, рд╕рд╛рде рд╣реА рдХреБрдЫ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рднреА рд╣реИрдВред рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдкрд░реНрдпрд╛рдкреНрдд рдФрд░ рдиреАрд░рд╕ рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЕрдиреНрдп рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рднреА рдПрдореНрдмреЗрдбреЗрдб рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
рдХрд╛рд░реНрдп
рдпрд╣ рдЯреНрд░реИрдХ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдореЙрдбрд▓ рдореЗрдВ рдбреЗрдЯрд╛ рдХрд┐рд╕рдиреЗ рдмрдирд╛рдпрд╛ рдФрд░ / рдпрд╛ рдХрд┐рд╕рдиреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ред
рд╡рд┐рдЪрд╛рд░
рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░реЗрдВ рддрд╛рдХрд┐ рд╕рдорд╛рдзрд╛рди рдХрд┐рд╕реА рднреА рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЖрд╕рд╛рдиреА рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред
рдирд┐рд░реНрдгрдп
рдЖрджрд░реНрд╢
рдЪреВрдВрдХрд┐ рд╣рдо рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЕрдкрдиреЗ рднрд╡рд┐рд╖реНрдп рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рд╕ рдореЙрдбрд▓ рдореЗрдВ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдорд┐рдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдЬреЛрдбрд╝рдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реИред рдорд┐рдХреНрд╕рд┐рди рдПрдХ рдРрд╕рд╛ рд╡рд░реНрдЧ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдореБрдЦреНрдп рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпреЗ create_by, updated_by рдлрд╝реАрд▓реНрдб рд╣реЛрдВрдЧреЗред
from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ class CreatedByMixin(models.Model): created_by = models.ForeignKey(User, verbose_name=_('Created by'), related_name='%(class)s_created_items', ) class Meta: abstract=True class UpdatedByMixin(models.Model): updated_by = models.ForeignKey(User, verbose_name=_('Updated by'), related_name='%(class)s_updated_items', ) class Meta: abstract = True class CreatedUpdatedByMixin(CreatedByMixin, UpdatedByMixin): class Meta: abstract = True
рд╣рдордиреЗ рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рддреАрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд░реНрдЧ рдмрдирд╛рдП рд╣реИрдВ: рдЬрдм рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╣реА рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕рдиреЗ рдмрдирд╛рдпрд╛, рдЬрдм рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рд╡рд╣реА рд╣реИ рдЬреЛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рдЬрдм рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдорд╛рдпрдиреЗ рд░рдЦрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕рдиреЗ рдмрдирд╛рдпрд╛ рдФрд░ рдХрд┐рд╕рдиреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ред
рдЕрдм рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдореЗрдВ рдбреЗрдЯрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдХрд┐рд╕рдиреЗ рдмрдирд╛рдпрд╛ рдФрд░ рдХрд┐рд╕рдиреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛, рдЖрдк рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдореЙрдбрд▓ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рдХреИрд╕реЗ рдкрддрд╛ рдХрд░реЗрдВ рдХрд┐ рдХрд┐рд╕рдиреЗ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрдирд╛рдИ / рдЕрдкрдбреЗрдЯ рдХреА?
- рд╕рд┐рдЧреНрдирд▓ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореЙрдбрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд░реВрдк рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ рдпрд╛ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдпрдерд╛рд╕рдВрднрд╡ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рдПрдВ?
from django.db import models from whovedonethis import models as who_models class TestCreatedUpdated(who_models.CreatedUpdatedByMixin): value = models.CharField('Value', max_length=255)
рдмрдЪрдд рд░рд┐рдХреЙрд░реНрдб
рдЕрдм рдореЙрдбрд▓ рдореЗрдВ рдлрд╝реАрд▓реНрдб рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреИрд╕реЗ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рдерд╛, рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ред рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрдИ рд╕рдорд╛рдзрд╛рди рд╣реИрдВ:
- рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдлреЙрд░реНрдо рдореЗрдВ рд╕реЗрд╡ рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд▓реЛрдб рдХрд░реЗрдВ
- рджреЗрдЦрдиреЗ рдореЗрдВ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд░рддреЗ рд╕рдордп рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬреЛрдбрд╝реЗрдВ
- рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдУрд╡рд░рд▓реЛрдб рд╕реЗрд╡ () рд╡рд┐рдзрд┐
- рд╕рдВрдХреЗрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдмрд╕реЗ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рддрд░реАрдХрд╛ рд╕рдВрдХреЗрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдХреБрдЫ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╛ рд╕рдорд╛рдзрд╛рди рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдирд╣реАрдВ рд╣реИред
рд╕рд┐рдЧреНрдирд▓ рдПрдХ рдмрд╣реБрдд рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рд╣реИ рдЬрд┐рд╕рдХреЗ рд╕рд╛рде django рдЖрдкрдХреЛ рд╕рд┐рд╕реНрдЯрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ (рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдмрдирд╛рдиреЗ рдпрд╛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП) рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдХреБрдЫ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реЛрддреА рд╣реИрдВ:
- рдХреИрд╕реЗ рдкрддрд╛ рдХрд░реЗрдВ рдХрд┐ рдХрд┐рд╕рдиреЗ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрдирд╛рдИ / рдЕрдкрдбреЗрдЯ рдХреА?
- рд╕рд┐рдЧреНрдирд▓ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореЙрдбрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВред рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд░реВрдк рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ рдпрд╛ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдпрдерд╛рд╕рдВрднрд╡ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдмрдирд╛рдПрдВ?
рдХреИрд╕реЗ рдкрддрд╛ рдХрд░реЗрдВ рдХрд┐ рдХрд┐рд╕рдиреЗ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдмрдирд╛рдИ / рдЕрдкрдбреЗрдЯ рдХреА?
рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдЖрдорддреМрд░ рдкрд░ рдЕрдиреБрд░реЛрдз рдЪрд░ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ
рдкреВрд░реНрд╡_ рд╕рд┐рдЧреНрдирд▓ рдХреЗ рджрд╛рдпрд░реЗ рдореЗрдВ рдирд╣реАрдВ рдЖрддреА рд╣реИред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
рд╕рд┐рдВрдЧрд▓рдЯрди рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ред рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╣рдорд╛рд░реЗ
рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
class Singleton(type): ''' Singleton pattern requires for LoggedInUser class ''' def __init__(cls, name, bases, dicts): cls.instance = None def __call__(cls, *args, **kwargs): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kwargs) return cls.instance class NotLoggedInUserException(Exception): ''' ''' def __init__(self, val='No users have been logged in'): self.val = val super(NotLoggedInUser, self).__init__() def __str__(self): return self.val class LoggedInUser(object): __metaclass__ = Singleton user = None def set_user(self, request): if request.user.is_authenticated(): self.user = request.user @property def current_user(self): ''' Return current user or raise Exception ''' if self.user is None: raise NotLoggedInUserException() return self.user @property def have_user(self): return not user is None from whovedonethis.loggedinuser import LoggedInUser class LoggedInUserMiddleware(object): ''' Insert this middleware after django.contrib.auth.middleware.AuthenticationMiddleware ''' def process_request(self, request): ''' Returned None for continue request ''' logged_in_user = LoggedInUser() logged_in_user.set_user(request) return None
рд╕рдВрдХреЗрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдХреНрдпрд╛ рд╣реИред
рдЪреВрдВрдХрд┐ рд╕рд┐рдЧреНрдирд▓ рдлрд╝рдВрдХреНрд╢рдВрд╕ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдбреЗрдХреЛрд░реЗрдЯрд░ рдирд╣реАрдВ рд▓рд┐рдЦреЗрдВ, рдЬреЛ рд╣рдорд╛рд░реЗ рд╕рдВрдХреЗрддреЛрдВ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдмрджрд▓ рджреЗрдЧрд╛, рд╣рдореЗрдВ рдЙрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ рдЬреЛ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдПред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдЗрдП рдПрдХ рдЪреЗрдХ рдЬреЛрдбрд╝реЗрдВ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХрд┐рд╕ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдпрджрд┐ рдореЙрдбрд▓ рдореЗрдВ 'create_by_field / updated_by_field' рдлрд╝реАрд▓реНрдб рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ, рддреЛ рд╣рдо рдЗрд╕реЗ рдорд╛рдирдХ рдлрд╝реАрд▓реНрдб рдореЗрдВ рдЕрдиреНрдпрдерд╛ рдЕрдиреНрдпрдерд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВрдЧреЗред рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЛ рдХреЗрд╡рд▓ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдЗрд╕рдХреА рд╕рдВрд░рдЪрдирд╛, рд╣рдо рдлрдВрдХреНрд╢рдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдлрдВрдХреНрд╢рдВрд╕ рд╕реЗ рдХрд░реЗрдВрдЧреЗред
from functools import wraps from whovedonethis.loggedinuser import LoggedInUser def add_created_user(f): ''' Decorate pre_save signal for adding created user ''' @wraps(f) def wrapper(sender, instance, **kwargs): if not instance.id: created_by_attr = getattr(instance, "created_by_field", "created_by" ) setattr(instance, created_by_attr, LoggedInUser().current_user) return f(sender, instance, **kwargs) return wrapper def add_updated_user(f): ''' Decorate pre_save signal for adding created user ''' @wraps(f) def wrapper(sender, instance, **kwargs): updated_by_attr = getattr(instance, "updated_by_field", "updated_by" ) setattr(instance, updated_by_attr, LoggedInUser().current_user) return f(sender, instance, **kwargs) return wrapper add_created_and_updated_user = lambda x: add_created_user(add_updated_user(x)) add_created_and_updated_user.__doc__ =\ ''' Decorate pre_save signal for adding created and updated user '''
рдкрд░рд┐рдгрд╛рдо
рдЦреИрд░, рдпрд╣ рдореВрд▓ рд░реВрдк рд╕реЗ рд╣реИред рдЕрдм рдпрд╣ рд╕рдм рдХреБрдЫ рдПрдХ рд╕рд╛рде рд░рдЦрдиреЗ рдФрд░ рд╣рдорд╛рд░реЗ рдПрдореНрдмреЗрдбреЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИред
рднрдВрдбрд╛рд░:
- рддреИрдпрд╛рд░ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде: //github.com/Zpeg/whovedonethis.git
- рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде: //github.com/Zpeg/test_whovedonethis.it
рдкреБрдирд╢реНрдЪ
рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдФрд░ рддреНрд░реБрдЯрд┐ рд╕рдВрдХреЗрддреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╡рд░реНрддрдиреА рдФрд░ рд╡рд┐рд░рд╛рдо рдЪрд┐рд╣реНрди рдореЗрдВред
рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рд▓реЗрдЦрди
PyCon 2011 рдХреЗ рд╕рд╛рде рдПрдХ
рдХреЛрд░реА рдУрд░реНрдбреЗрдЯ рд╡рд╛рд░реНрддрд╛ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рдерд╛ред
рдпреБрдкреАрдбреАред
рдбреЗрдХреЛрд░реЗрдЯрд░ рдХреЗ рд╕рд╛рде рд╕рд┐рдЧреНрдирд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг:
from django.db.models.signals import pre_save from django.dispatch import receiver from whovedonethis import decorator from testlib.models import TestCreated @receiver(pre_save, sender=TestCreated) @decorator.add_created_user def pre_save_testcreated_handler(sender, instance, **kwargs): pass