Opened 15 years ago

Closed 8 years ago

#10107 closed New feature (fixed)

Allow mark_safe() to be used as a decorator

Reported by: matehat Owned by: Scott Vitale
Component: Utilities Version: dev
Severity: Normal Keywords:
Cc: mathieu.damours@…, mmitar@…, susan.tan.fleckerl@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I think the two safety markers located in django.utils.safestring could be improved a bit to help DRYing up a redundant situation. Say some function of a model or whatever class instance is often used in templates and instead of applying the safe filter to it everywhere it appears in the template code, the returned value is marked as safe. Now the following pattern can be DRYed up:

def some_method(self, arg):
  if arg == 1:
    return mark_safe(some_tags)
  elif arg == 2:
    return mark_safe(some_other_tags)
  elif arg == 3:
    return mark_safe(some_third_tags)

Sure there are better ways to organize this type of pattern but it shows my point. Instead of appying the marker everywhere data is returned, it could be used as a decorator on the whole method:

@mark_safe
def some_method(self, arg):
  if arg == 1:
    return some_tags
  elif arg == 2:
    return some_other_tags
  elif arg == 3:
    return some_third_tags

Anyway, I made the necessary patch, so take a look at it! The same is applied to the mark_for_escaping method for the same reasons.

Attachments (3)

safestring.diff (2.0 KB ) - added by matehat 15 years ago.
patch.2.diff (5.0 KB ) - added by matehat 15 years ago.
patch.diff (5.5 KB ) - added by matehat 15 years ago.
New patch for regressiontests, documentation and django.utils.safestring

Download all attachments as: .zip

Change History (22)

by matehat, 15 years ago

Attachment: safestring.diff added

comment:1 by matehat, 15 years ago

Owner: changed from nobody to matehat

comment:2 by Malcolm Tredinnick, 15 years ago

Triage Stage: UnreviewedAccepted

This isn't a bad idea. There are some improvements that jump out at me from reading the patch, however:

  1. Code must be Python 2.3 compatible, which means you can't use a decorator in any of this code (you're using one for one of the nested functions).
  2. Don't worry about allowing the case of @mark_safe(). That's just poor style, since the decorator/function never takes any arguments. People can get by with only writing @mark_safe. That removes the need for s=None, too, which avoids accidental errors.
  3. Patch needs to include documentation changes to describe the new usage.
  4. Patch needs to include test changes, so that we can verify it continues to keep on working in the future.

by matehat, 15 years ago

Attachment: patch.2.diff added

comment:3 by matehat, 15 years ago

The new patch includes fixes for python 2.3 compatibility and a test case for testing escaping behavior (though for a unknown reason, the file's content doesn't show up in trac ... I can only see its content when downloading it ...) I'm still unsure where I should put the documentation for this: in 'Custom template tags' (It's not quite designed for this) or in '(Template) Syntax overview' (though turning autoescaping off is only mentioned there for the template side of coding, i.e. for template designers).

comment:4 by matehat, 15 years ago

Needs documentation: set

comment:5 by dc, 15 years ago

Maybe offtopic, but in your case better use function with one exit point:

def some_method(self, arg):
  if arg == 1:
    tags = some_tags
  elif arg == 2:
    tags = some_other_tags
  elif arg == 3:
    tags = some_third_tags
  return mark_safe(tags)

comment:6 by matehat, 15 years ago

Yes, of course :P, I made up a simplistic situation that is rather a 'reduced' version of more complex cases, where a very complicated processing sometimes happen. Of course it can always be rearranged the way you suggested, but that can also make things less straightfoward.

comment:7 by matehat, 15 years ago

Sorry about the long time in adding patch to documentation for using mark_safe and mark_for_escaping as decorators. The new patch includes tests and documentation.

by matehat, 15 years ago

Attachment: patch.diff added

New patch for regressiontests, documentation and django.utils.safestring

comment:8 by Chris Beaven, 13 years ago

Severity: Normal
Type: New feature

comment:9 by Mitar, 13 years ago

Cc: mmitar@… added
Easy pickings: unset

comment:10 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:11 by Petr Dlouhý, 8 years ago

Where got this stuck? Is there any problem with the patch?

comment:12 by Tim Graham, 8 years ago

Component: Template systemUtilities
Summary: mark_safe and mark_for_escaping as decoratorsAllow mark_safe() to be used as a decorator

The patch is 7 years old, so needs to be updated to apply cleanly to trunk and conform to the guidelines of the PatchReviewChecklist.

I'd also suggest to drop the enhancement for mark_for_escaping() as that function is under consideration for deprecation in #24046.

comment:13 by Susan Tan, 8 years ago

Owner: changed from matehat to Susan Tan
Status: newassigned

comment:14 by Susan Tan, 8 years ago

Cc: susan.tan.fleckerl@… added
Patch needs improvement: set
Version: 1.0master

comment:15 by Susan Tan, 8 years ago

https://github.com/django/django/pull/6390 is the github pull request.

comment:16 by Scott Vitale, 8 years ago

Owner: changed from Susan Tan to Scott Vitale

Talked to susan at Pycon 2016 and created a new PR to incorporate the comments from her original work. New PR here: https://github.com/django/django/pull/6706

comment:17 by Tim Graham, 8 years ago

Needs documentation: unset

Left comments for improvement on the PR. Please uncheck "Patch needs improvement" after updating.

comment:18 by Scott Vitale, 8 years ago

Patch needs improvement: unset

comment:19 by Tim Graham <timograham@…>, 8 years ago

Resolution: fixed
Status: assignedclosed

In be729b6:

Fixed #10107 -- Allowed using mark_safe() as a decorator.

Thanks ArcTanSusan for the initial patch.

Note: See TracTickets for help on using tickets.
Back to Top