Ticket #2901: admin_log_with_site.diff

File admin_log_with_site.diff, 10.0 KB (added by Christopher Lenz <cmlenz@…>, 9 years ago)

Patch as described above

  • django/views/defaults.py

     
    2424    if absurl.startswith('http://'):
    2525        return http.HttpResponseRedirect(absurl)
    2626
     27    # Try to figure out the related site for the object
    2728    object_domain = None
     29    site = Site.objects.get_for_obj(obj)
     30    if site:
     31        object_domain = site.domain
    2832
    29     # Otherwise, we need to introspect the object's relationships for a
    30     # relation to the Site object
    31     opts = obj._meta
    32 
    33     # First, look for an many-to-many relationship to sites
    34     for field in opts.many_to_many:
    35         if field.rel.to is Site:
    36             try:
    37                 object_domain = getattr(obj, field.name).all()[0].domain
    38             except IndexError:
    39                 pass
    40             if object_domain is not None:
    41                 break
    42 
    43     # Next look for a many-to-one relationship to site
    44     if object_domain is None:
    45         for field in obj._meta.fields:
    46             if field.rel and field.rel.to is Site:
    47                 try:
    48                     object_domain = getattr(obj, field.name).domain
    49                 except Site.DoesNotExist:
    50                     pass
    51                 if object_domain is not None:
    52                     break
    53 
    5433    # Fall back to the current site (if possible)
    5534    if object_domain is None:
    5635        try:
  • django/contrib/sites/models.py

     
    22from django.utils.translation import gettext_lazy as _
    33
    44class SiteManager(models.Manager):
     5
    56    def get_current(self):
    67        from django.conf import settings
    78        return self.get(pk=settings.SITE_ID)
    89
     10    def get_for_object(self, obj):
     11        """
     12        Returns the Site object for the given model object, if that object has
     13        a corresponding relation. Otherwise it returns None.
     14        """
     15        opts = obj._meta
     16
     17        # First, look for an many-to-many relationship to sites
     18        for field in opts.many_to_many:
     19            if field.rel.to is Site:
     20                if getattr(obj, field.name):
     21                    try:
     22                        return getattr(obj, field.name).all()[0]
     23                    except IndexError:
     24                        pass
     25
     26        # Next look for a many-to-one relationship to sites
     27        for field in obj._meta.fields:
     28            if field.rel and field.rel.to is Site:
     29                return getattr(obj, field.name)
     30
     31        # Cannot determine a direct relation to sites, so return None
     32        return None
     33
    934class Site(models.Model):
    1035    domain = models.CharField(_('domain name'), maxlength=100)
    1136    name = models.CharField(_('display name'), maxlength=50)
  • django/contrib/admin/templatetags/log.py

     
    11from django import template
     2from django.conf import settings
    23from django.contrib.admin.models import LogEntry
     4from django.db import models
    35
    46register = template.Library()
    57
    68class AdminLogNode(template.Node):
    7     def __init__(self, limit, varname, user):
    8         self.limit, self.varname, self.user = limit, varname, user
     9    def __init__(self, limit, varname, user, site):
     10        self.limit = limit
     11        self.varname = varname
     12        self.user = user
     13        self.site = site
    914
    1015    def __repr__(self):
    1116        return "<GetAdminLog Node>"
     
    1318    def render(self, context):
    1419        if self.user is not None and not self.user.isdigit():
    1520            self.user = context[self.user].id
    16         context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit]
     21
     22        entries = LogEntry.objects.filter(user__id__exact=self.user)
     23        if self.site:
     24            if not self.site.isdigit():
     25                self.site = context[self.site].id
     26            entries.filter(models.Q(site_id=self.site) |
     27                           models.Q(site_id__isnull=True))
     28
     29        context[self.varname] = entries.select_related()[:self.limit]
    1730        return ''
    1831
    1932class DoGetAdminLog:
     
    2336    Usage::
    2437
    2538        {% get_admin_log [limit] as [varname] for_user [context_var_containing_user_obj] %}
     39       
     40    or::
    2641
     42        {% get_admin_log [limit] as [varname] for_site [context_var_containing_site_obj] %}
     43
    2744    Examples::
    2845
    2946        {% get_admin_log 10 as admin_log for_user 23 %}
    30         {% get_admin_log 10 as admin_log for_user user %}
     47        {% get_admin_log 10 as admin_log for_user varname %}
     48        {% get_admin_log 10 as admin_log for_site %}
     49        {% get_admin_log 10 as admin_log for_site 2 %}
     50        {% get_admin_log 10 as admin_log for_site varname %}
    3151        {% get_admin_log 10 as admin_log %}
    3252
    3353    Note that ``context_var_containing_user_obj`` can be a hard-coded integer
    3454    (user ID) or the name of a template context variable containing the user
    35     object whose ID you want.
     55    object whose ID you want. The ``context_var_containing_site_obj`` works the
     56    same way, except that when you omit a value, it uses the current site.
    3657    """
    3758    def __init__(self, tag_name):
    3859        self.tag_name = tag_name
     
    4566            raise template.TemplateSyntaxError, "First argument in '%s' must be an integer" % self.tag_name
    4667        if tokens[2] != 'as':
    4768            raise template.TemplateSyntaxError, "Second argument in '%s' must be 'as'" % self.tag_name
     69        user = site = None
    4870        if len(tokens) > 4:
    49             if tokens[4] != 'for_user':
    50                 raise template.TemplateSyntaxError, "Fourth argument in '%s' must be 'for_user'" % self.tag_name
    51         return AdminLogNode(limit=tokens[1], varname=tokens[3], user=(len(tokens) > 5 and tokens[5] or None))
     71            if tokens[4] not in ('for_user', 'for_site'):
     72                raise template.TemplateSyntaxError, "Fourth argument in '%s' must be 'for_user' or 'for_site'" % self.tag_name
     73            if tokens[4] == 'for_user':
     74                user = len(tokens) > 5 and tokens[5] or None
     75            else:
     76                site = len(tokens) > 5 and tokens[5] or str(settings.SITE_ID)
     77        return AdminLogNode(limit=tokens[1], varname=tokens[3], user=user, site=site)
    5278
    5379register.tag('get_admin_log', DoGetAdminLog('get_admin_log'))
  • django/contrib/admin/models.py

     
    11from django.db import models
    22from django.contrib.contenttypes.models import ContentType
    33from django.contrib.auth.models import User
     4from django.contrib.sites.models import Site
    45from django.utils.translation import gettext_lazy as _
    56
    67ADDITION = 1
     
    89DELETION = 3
    910
    1011class LogEntryManager(models.Manager):
    11     def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
    12         e = self.model(None, None, user_id, content_type_id, object_id, object_repr[:200], action_flag, change_message)
     12    def log_action(self, user, model, obj, action, message=''):
     13        site_id = None
     14        site = Site.objects.get_for_object(obj)
     15        if site:
     16            site_id = site.id
     17        e = self.model(None, None, user.id, site_id,
     18                       ContentType.objects.get_for_model(model).id,
     19                       obj._get_pk_val(), str(obj)[:200], action, message)
    1320        e.save()
    1421
    1522class LogEntry(models.Model):
    1623    action_time = models.DateTimeField(_('action time'), auto_now=True)
    1724    user = models.ForeignKey(User)
     25    site = models.ForeignKey(Site, blank=True, null=True)
    1826    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    1927    object_id = models.TextField(_('object id'), blank=True, null=True)
    2028    object_repr = models.CharField(_('object repr'), maxlength=200)
  • django/contrib/admin/views/main.py

     
    253253        if not errors:
    254254            new_object = manipulator.save(new_data)
    255255            pk_value = new_object._get_pk_val()
    256             LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), ADDITION)
     256            LogEntry.objects.log_action(request.user, model, new_object, ADDITION)
    257257            msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object}
    258258            # Here, we distinguish between different save types by checking for
    259259            # the presence of keys in request.POST.
     
    340340            change_message = ' '.join(change_message)
    341341            if not change_message:
    342342                change_message = _('No fields changed.')
    343             LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, pk_value, str(new_object), CHANGE, change_message)
     343            LogEntry.objects.log_action(request.user, model, new_object, CHANGE, change_message)
    344344
    345345            msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object}
    346346            if request.POST.has_key("_continue"):
     
    507507            raise PermissionDenied
    508508        obj_display = str(obj)
    509509        obj.delete()
    510         LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, object_id, obj_display, DELETION)
     510        LogEntry.objects.log_action(request.user, model, obj, DELETION)
    511511        request.user.message_set.create(message=_('The %(name)s "%(obj)s" was deleted successfully.') % {'name': opts.verbose_name, 'obj': obj_display})
    512512        return HttpResponseRedirect("../../")
    513513    extra_context = {
Back to Top