mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
PEP8 compliance and cleanup.
This commit is contained in:
@@ -2,18 +2,20 @@
|
||||
import time
|
||||
import re
|
||||
import os
|
||||
import time, random, hashlib
|
||||
import time
|
||||
import random
|
||||
import hashlib
|
||||
import lxml.html
|
||||
from lxml import etree
|
||||
from django.conf import settings
|
||||
from django.template.loader import render_to_string
|
||||
from django.template import Template, Context
|
||||
from django.utils.translation import ugettext as _
|
||||
from modoboa.lib.webutils import _render
|
||||
from modoboa.lib.emailutils import decode
|
||||
|
||||
attached_map = {}
|
||||
|
||||
|
||||
class MBconnector(object):
|
||||
def __init__(self, address, port):
|
||||
self.address = address
|
||||
@@ -22,6 +24,7 @@ class MBconnector(object):
|
||||
def messages_count(self, **kwargs):
|
||||
pass
|
||||
|
||||
|
||||
class Page(object):
|
||||
def __init__(self, pageid, id_start, id_stop, items,
|
||||
items_per_page, has_previous, has_next,
|
||||
@@ -53,6 +56,7 @@ class Page(object):
|
||||
lid += 1
|
||||
return lid
|
||||
|
||||
|
||||
class Paginator(object):
|
||||
def __init__(self, total, elems_per_page):
|
||||
self.total = total
|
||||
@@ -65,7 +69,7 @@ class Paginator(object):
|
||||
id_start = self.elems_per_page * page + 1
|
||||
id_stop = id_start + self.elems_per_page - 1
|
||||
return (id_start, id_stop)
|
||||
|
||||
|
||||
def getpage(self, page):
|
||||
if page < 1:
|
||||
return None
|
||||
@@ -85,6 +89,7 @@ class Paginator(object):
|
||||
p.paginator = self
|
||||
return p
|
||||
|
||||
|
||||
class EmailListing(object):
|
||||
|
||||
def __init__(self, baseurl=None, folder=None, elems_per_page=40,
|
||||
@@ -113,21 +118,25 @@ class EmailListing(object):
|
||||
def render_navbar(page, baseurl=None):
|
||||
if page is None:
|
||||
return ""
|
||||
context = {"page": page, "STATIC_URL": settings.STATIC_URL, "baseurl": baseurl}
|
||||
context = {
|
||||
"page": page, "STATIC_URL": settings.STATIC_URL, "baseurl": baseurl
|
||||
}
|
||||
return render_to_string("common/pagination_bar.html", context)
|
||||
|
||||
|
||||
def fetch(self, request, id_start, id_stop):
|
||||
table = self.tbltype(request,
|
||||
self.mbc.fetch(start=id_start, stop=id_stop,
|
||||
mbox=self.folder,
|
||||
nbelems=self.elems_per_page))
|
||||
table = self.tbltype(
|
||||
request,
|
||||
self.mbc.fetch(start=id_start, stop=id_stop,
|
||||
mbox=self.folder,
|
||||
nbelems=self.elems_per_page)
|
||||
)
|
||||
tpl = Template("""
|
||||
<form method="POST" id="listingform">
|
||||
{{ table }}
|
||||
</form>""")
|
||||
return tpl.render(
|
||||
Context({
|
||||
"table" : table.render(withheader=self.show_listing_headers)
|
||||
"table": table.render(withheader=self.show_listing_headers)
|
||||
})
|
||||
)
|
||||
|
||||
@@ -139,10 +148,11 @@ class EmailListing(object):
|
||||
listing = self.fetch(request, page.id_start, page.id_stop)
|
||||
return dict(listing=listing, navbar=self.render_navbar(page, self.baseurl))
|
||||
|
||||
|
||||
def parse_search_parameters(request):
|
||||
if request.GET.has_key("pattern"):
|
||||
if 'pattern' in request.GET:
|
||||
request.session["pattern"] = re.escape(request.GET["pattern"])
|
||||
if request.GET.has_key("criteria"):
|
||||
if 'criteria' in request.GET:
|
||||
request.session["criteria"] = request.GET["criteria"]
|
||||
else:
|
||||
request.session["criteria"] = ["from_addr"]
|
||||
@@ -150,4 +160,3 @@ def parse_search_parameters(request):
|
||||
for p in ["pattern", "criteria"]:
|
||||
if p in request.session.keys():
|
||||
del request.session[p]
|
||||
|
||||
|
||||
+29
-15
@@ -8,19 +8,20 @@ from django.utils.encoding import force_unicode
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.html import conditional_escape
|
||||
|
||||
|
||||
class CreationWizard(object):
|
||||
def __init__(self, done_cb):
|
||||
self.steps = []
|
||||
self.done_cb = done_cb
|
||||
|
||||
def add_step(self, cls, title, buttons, formtpl=None, new_args=None):
|
||||
self.steps += [dict(cls=cls, title=title, buttons=buttons,
|
||||
self.steps += [dict(cls=cls, title=title, buttons=buttons,
|
||||
formtpl=formtpl, new_args=new_args)]
|
||||
|
||||
def create_forms(self, data=None):
|
||||
for step in self.steps:
|
||||
args = []
|
||||
if step.has_key("new_args") and step["new_args"]:
|
||||
if 'new_args' in step and step["new_args"]:
|
||||
args += step["new_args"]
|
||||
if data:
|
||||
args.append(data)
|
||||
@@ -46,6 +47,7 @@ class CreationWizard(object):
|
||||
def get_title(self, stepid):
|
||||
return "%d. %s" % (stepid + 1, self.steps[stepid]["title"])
|
||||
|
||||
|
||||
class DynamicForm(object):
|
||||
|
||||
def _create_field(self, typ, name, value=None, pos=None):
|
||||
@@ -66,12 +68,13 @@ class DynamicForm(object):
|
||||
ndata = self.data.copy()
|
||||
values.reverse()
|
||||
for v in values:
|
||||
if self.fields.has_key(v[0]):
|
||||
if v[0] in self.fields:
|
||||
continue
|
||||
self._create_field(typ, v[0])
|
||||
ndata[v[0]] = v[1]
|
||||
self.data = ndata
|
||||
|
||||
|
||||
class TabForms(object):
|
||||
"""
|
||||
Simple forms container
|
||||
@@ -99,21 +102,21 @@ class TabForms(object):
|
||||
fd["instance"] = classes[fd["id"]](*args, **kwargs)
|
||||
else:
|
||||
fd["instance"] = fd["cls"](*args, **kwargs)
|
||||
map(lambda fd: self.forms.remove(fd), to_remove)
|
||||
self.forms = [form for form in self.forms if not form in to_remove]
|
||||
if self.forms:
|
||||
self.active_id = self.forms[0]["id"]
|
||||
|
||||
def _before_is_valid(self, form):
|
||||
return True
|
||||
|
||||
|
||||
def is_valid(self, mandatory_only=False, optional_only=False):
|
||||
to_remove = []
|
||||
for f in self.forms:
|
||||
if mandatory_only and \
|
||||
(not f.has_key("mandatory") or not f["mandatory"]):
|
||||
(not 'mandatory' in f or not f["mandatory"]):
|
||||
continue
|
||||
elif optional_only and \
|
||||
(f.has_key("mandatory") and f["mandatory"]):
|
||||
('mandatory' in f and f["mandatory"]):
|
||||
continue
|
||||
if not self._before_is_valid(f):
|
||||
to_remove.append(f)
|
||||
@@ -121,7 +124,7 @@ class TabForms(object):
|
||||
if not f["instance"].is_valid():
|
||||
self.active_id = f["id"]
|
||||
return False
|
||||
map(lambda fd: self.forms.remove(fd), to_remove)
|
||||
self.forms = [f for f in self.forms if not f in to_remove]
|
||||
return True
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
@@ -132,7 +135,7 @@ class TabForms(object):
|
||||
if f["id"] == tabid:
|
||||
self.forms.remove(f)
|
||||
break
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return self.forward()
|
||||
|
||||
@@ -144,6 +147,7 @@ class TabForms(object):
|
||||
# Custom fields from here
|
||||
#
|
||||
|
||||
|
||||
def is_valid_host(host):
|
||||
"""IDN compatible domain validator
|
||||
"""
|
||||
@@ -152,6 +156,7 @@ def is_valid_host(host):
|
||||
is_valid_host._re = re.compile(r'^([0-9a-z][-\w]*[0-9a-z]\.)+[a-z0-9\-]{2,15}$')
|
||||
return bool(is_valid_host._re.match(host))
|
||||
|
||||
|
||||
def validate_domain_name(value):
|
||||
if not is_valid_host(value):
|
||||
raise ValidationError(_('Enter a valid domain name'), 'invalid')
|
||||
@@ -162,8 +167,8 @@ class DomainNameField(CharField):
|
||||
A subclass of CharField that only accepts a valid domain name.
|
||||
"""
|
||||
default_error_messages = {
|
||||
'invalid' : _('Enter a valid domain name')
|
||||
}
|
||||
'invalid': _('Enter a valid domain name')
|
||||
}
|
||||
|
||||
default_validators = [validate_domain_name]
|
||||
|
||||
@@ -179,16 +184,23 @@ class CustomRadioInput(RadioInput):
|
||||
else:
|
||||
label_for = ''
|
||||
choice_label = conditional_escape(force_unicode(self.choice_label))
|
||||
return mark_safe(u'<label class="radio inline" %s>%s %s</label>' % (label_for, self.tag(), choice_label))
|
||||
return mark_safe(
|
||||
u'<label class="radio inline" %s>%s %s</label>'
|
||||
% (label_for, self.tag(), choice_label)
|
||||
)
|
||||
|
||||
|
||||
class InlineRadioRenderer(RadioSelect.renderer):
|
||||
def __iter__(self):
|
||||
for i, choice in enumerate(self.choices):
|
||||
yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i)
|
||||
yield CustomRadioInput(
|
||||
self.name, self.value, self.attrs.copy(), choice, i
|
||||
)
|
||||
|
||||
def render(self):
|
||||
return mark_safe(u'\n'.join([u'%s\n' % force_unicode(w) for w in self]))
|
||||
return mark_safe(
|
||||
u'\n'.join([u'%s\n' % force_unicode(w) for w in self])
|
||||
)
|
||||
|
||||
|
||||
class InlineRadioSelect(RadioSelect):
|
||||
@@ -203,6 +215,8 @@ class SeparatorField(Field):
|
||||
|
||||
class YesNoField(ChoiceField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs["choices"] = [("yes", ugettext_lazy("Yes")), ("no", ugettext_lazy("No"))]
|
||||
kwargs["choices"] = [
|
||||
("yes", ugettext_lazy("Yes")), ("no", ugettext_lazy("No"))
|
||||
]
|
||||
kwargs["widget"] = InlineRadioSelect
|
||||
super(YesNoField, self).__init__(*args, **kwargs)
|
||||
|
||||
+23
-11
@@ -70,14 +70,14 @@ class GenericParametersForm(forms.Form):
|
||||
|
||||
class AdminParametersForm(GenericParametersForm):
|
||||
def _load_initial_values(self):
|
||||
from models import Parameter
|
||||
from .models import Parameter
|
||||
|
||||
names = ["%s.%s" % (self.app, name.upper()) for name in self.fields.keys()]
|
||||
for p in Parameter.objects.filter(name__in=names):
|
||||
self.fields[p.shortname].initial = p.value
|
||||
|
||||
def save(self):
|
||||
from models import Parameter
|
||||
from .models import Parameter
|
||||
from modoboa.lib.formutils import SeparatorField
|
||||
|
||||
for name, value in self.cleaned_data.items():
|
||||
@@ -111,7 +111,7 @@ class UserParametersForm(GenericParametersForm):
|
||||
def _load_initial_values(self):
|
||||
if self.user is None:
|
||||
return
|
||||
from models import UserParameter
|
||||
from .models import UserParameter
|
||||
|
||||
names = ["%s.%s" % (self.app, name.upper()) for name in self.fields.keys()]
|
||||
for p in UserParameter.objects.filter(user=self.user, name__in=names):
|
||||
@@ -122,7 +122,7 @@ class UserParametersForm(GenericParametersForm):
|
||||
return True
|
||||
|
||||
def save(self):
|
||||
from models import UserParameter
|
||||
from .models import UserParameter
|
||||
from modoboa.lib.formutils import SeparatorField
|
||||
|
||||
for name, value in self.cleaned_data.items():
|
||||
@@ -141,7 +141,7 @@ class UserParametersForm(GenericParametersForm):
|
||||
def register(formclass, label):
|
||||
"""Register a form class containing parameters
|
||||
|
||||
formclass must inherit from ``AdminParametersForm`` of
|
||||
formclass must inherit from ``AdminParametersForm`` or
|
||||
``UserParametersForm``.
|
||||
|
||||
:param formclass: a form class
|
||||
@@ -155,7 +155,9 @@ def register(formclass, label):
|
||||
level = 'U'
|
||||
else:
|
||||
raise RuntimeError("Unknown parameter class")
|
||||
_params[level][formclass.app] = {"label": label, "form": formclass, "defaults": {}}
|
||||
_params[level][formclass.app] = {
|
||||
"label": label, "form": formclass, "defaults": {}
|
||||
}
|
||||
form = formclass()
|
||||
for name, field in form.fields.items():
|
||||
if type(field) is SeparatorField:
|
||||
@@ -198,7 +200,7 @@ def __guess_extension():
|
||||
|
||||
|
||||
def save_admin(name, value, app=None):
|
||||
from models import Parameter
|
||||
from .models import Parameter
|
||||
|
||||
if app is None:
|
||||
app = __guess_extension()
|
||||
@@ -215,7 +217,7 @@ def save_admin(name, value, app=None):
|
||||
|
||||
|
||||
def save_user(user, name, value, app=None):
|
||||
from models import UserParameter
|
||||
from .models import UserParameter
|
||||
|
||||
if app is None:
|
||||
app = __guess_extension()
|
||||
@@ -240,7 +242,7 @@ def get_admin(name, app=None, raise_error=True):
|
||||
:param app: the application owning the parameter
|
||||
:return: the corresponding value as a string
|
||||
"""
|
||||
from models import Parameter
|
||||
from .models import Parameter
|
||||
|
||||
if app is None:
|
||||
app = __guess_extension()
|
||||
@@ -267,7 +269,7 @@ def get_user(user, name, app=None, raise_error=True):
|
||||
:param app: the application owning the parameter
|
||||
:return: the corresponding value as a string
|
||||
"""
|
||||
from models import UserParameter
|
||||
from .models import UserParameter
|
||||
|
||||
if app is None:
|
||||
app = __guess_extension()
|
||||
@@ -284,7 +286,13 @@ def get_user(user, name, app=None, raise_error=True):
|
||||
return p.value.decode("unicode_escape")
|
||||
|
||||
|
||||
def get_sorted_apps(level, first="admin"):
|
||||
def get_sorted_apps(level, first="core"):
|
||||
"""Retrieve the sorted list of all registerd applications.
|
||||
|
||||
:param str level: application level
|
||||
:param str first: force the first item of the result
|
||||
:rtype: list
|
||||
"""
|
||||
sorted_apps = []
|
||||
if first in _params[level]:
|
||||
sorted_apps.append(first)
|
||||
@@ -296,6 +304,10 @@ def get_sorted_apps(level, first="admin"):
|
||||
|
||||
|
||||
def get_admin_forms(*args, **kwargs):
|
||||
"""Get all admin level forms.
|
||||
|
||||
Generates an instance of each declared form.
|
||||
"""
|
||||
for app in get_sorted_apps('A'):
|
||||
formdef = _params['A'][app]
|
||||
yield {"label": formdef["label"],
|
||||
|
||||
+13
-18
@@ -4,29 +4,24 @@
|
||||
This module extra functions/shortcuts to communicate with the system
|
||||
(executing commands, etc.)
|
||||
"""
|
||||
import logging
|
||||
import logging.handlers
|
||||
import subprocess
|
||||
from modoboa.lib import parameters
|
||||
|
||||
def exec_cmd(cmd, sudo_user=None, **kwargs):
|
||||
import subprocess
|
||||
|
||||
def exec_cmd(cmd, sudo_user=None, **kwargs):
|
||||
"""Execute a shell command.
|
||||
|
||||
Run a command using the current user. Set :keyword:`sudo_user` if
|
||||
you need different privileges.
|
||||
|
||||
:param str cmd: the command to execute
|
||||
:param str sudo_user: a valid system username
|
||||
:rtype: tuple
|
||||
:return: return code, command output
|
||||
"""
|
||||
if sudo_user is not None:
|
||||
cmd = "sudo -u %s %s" % (sudo_user, cmd)
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, **kwargs)
|
||||
output = p.communicate()[0]
|
||||
return p.returncode, output
|
||||
|
||||
def __log(msg, facility=logging.handlers.SysLogHandler.LOG_AUTH):
|
||||
logger = logging.getLogger('modoboa')
|
||||
logger.setLevel(logging.DEBUG)
|
||||
handler = logging.handlers.SysLogHandler(address='/dev/log', facility=facility)
|
||||
formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s')
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
return logger
|
||||
|
||||
def log_warning(msg):
|
||||
logger = __log(msg)
|
||||
logger.warning(msg)
|
||||
|
||||
+23
-35
@@ -16,6 +16,7 @@ from django.template import Template, RequestContext, Context
|
||||
from django.template.loader import render_to_string
|
||||
from templatetags.libextras import render_link
|
||||
|
||||
|
||||
class Column(object):
|
||||
"""Simple column representation
|
||||
"""
|
||||
@@ -24,7 +25,7 @@ class Column(object):
|
||||
self.sortable = True
|
||||
for k, v in kwargs.iteritems():
|
||||
setattr(self, k, v)
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
try:
|
||||
label = getattr(self, "label")
|
||||
@@ -51,6 +52,7 @@ class Column(object):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
class SelectionColumn(Column):
|
||||
"""Specific column: selection
|
||||
|
||||
@@ -64,7 +66,7 @@ class SelectionColumn(Column):
|
||||
|
||||
def render(self, value, selection):
|
||||
return "<input type='checkbox' id='%(id)s' name='select_%(value)s' value='%(value)s' %(checked)s/>" \
|
||||
% {'id': self.name, 'value': value,
|
||||
% {'id': self.name, 'value': value,
|
||||
"checked": "checked=''" if selection else ""}
|
||||
|
||||
def transform(self, row, col, table):
|
||||
@@ -72,9 +74,10 @@ class SelectionColumn(Column):
|
||||
col["value"] = self.render(row[table.idkey], selection)
|
||||
col["safe"] = True
|
||||
|
||||
|
||||
class ImgColumn(Column):
|
||||
"""Specific column: image
|
||||
|
||||
|
||||
This kind of column only contains images tags (<img>).
|
||||
"""
|
||||
def __str__(self):
|
||||
@@ -86,7 +89,7 @@ class ImgColumn(Column):
|
||||
|
||||
def render(self, value):
|
||||
if type(value) in [list, tuple]:
|
||||
return "".join(map(lambda i: "<img src='%s' />" % i, value))
|
||||
return "".join(["<img src='%s' />" % i for i in value])
|
||||
return "<img src='%s' />" % value
|
||||
|
||||
def transform(self, row, col, table):
|
||||
@@ -100,6 +103,7 @@ class ImgColumn(Column):
|
||||
pass
|
||||
col["safe"] = True
|
||||
|
||||
|
||||
class DivColumn(Column):
|
||||
def __str__(self):
|
||||
return ""
|
||||
@@ -111,6 +115,7 @@ class DivColumn(Column):
|
||||
col["value"] = self.render()
|
||||
col["safe"] = True
|
||||
|
||||
|
||||
class ActionColumn(Column):
|
||||
def render(self, fct, user, rowid):
|
||||
return fct(user, rowid)
|
||||
@@ -119,10 +124,11 @@ class ActionColumn(Column):
|
||||
col["value"] = self.render(self.defvalue, table.request.user, row[table.idkey])
|
||||
col["safe"] = True
|
||||
|
||||
|
||||
class LinkColumn(Column):
|
||||
def render(self, rowid, value):
|
||||
linkdef = dict(label=value, modal=self.modal)
|
||||
if type(self.urlpattern) == dict:
|
||||
if type(self.urlpattern) is dict:
|
||||
t, value = rowid.split(":")
|
||||
linkdef.update(url=reverse(self.urlpattern[t], args=[value]),
|
||||
modalcb=self.modalcb[t])
|
||||
@@ -135,12 +141,15 @@ class LinkColumn(Column):
|
||||
col["value"] = self.render(row[table.idkey], row[self.name])
|
||||
col["safe"] = True
|
||||
|
||||
|
||||
class Table(object):
|
||||
tableid = ""
|
||||
|
||||
def __init__(self, request, rows={}):
|
||||
def __init__(self, request, rows=None):
|
||||
self.columns = []
|
||||
self.request = request
|
||||
if rows is None:
|
||||
rows = {}
|
||||
try:
|
||||
order = getattr(self, "cols_order")
|
||||
except AttributeError:
|
||||
@@ -168,13 +177,13 @@ class Table(object):
|
||||
self.rows = []
|
||||
trcpt = 0
|
||||
for row in rows:
|
||||
nrow = {"id" : row[self.idkey], "cols" : [], "trcpt" : trcpt}
|
||||
nrow = {"id": row[self.idkey], "cols": [], "trcpt": trcpt}
|
||||
for name in ["style", "options"]:
|
||||
if row.has_key(name):
|
||||
if name in row:
|
||||
nrow[name] = row[name]
|
||||
|
||||
|
||||
for c in self.columns:
|
||||
newcol = {"name" : c.name}
|
||||
newcol = {"name": c.name}
|
||||
for key in ["width", "align", "cssclass"]:
|
||||
try:
|
||||
newcol[key] = getattr(c, key)
|
||||
@@ -184,7 +193,7 @@ class Table(object):
|
||||
nrow["cols"] += [newcol]
|
||||
self.rows += [nrow]
|
||||
trcpt += 1
|
||||
|
||||
|
||||
def _rows_from_model(self, objects, include_type_in_id=False):
|
||||
rows = []
|
||||
for obj in objects:
|
||||
@@ -232,32 +241,11 @@ class Table(object):
|
||||
</table>
|
||||
""")
|
||||
return t.render(RequestContext(self.request, {
|
||||
"table" : self, "tableid" : self.tableid, "styles" : styles,
|
||||
"withheader" : withheader
|
||||
}))
|
||||
"table": self, "tableid": self.tableid, "styles": styles,
|
||||
"withheader": withheader
|
||||
}))
|
||||
|
||||
t = Template("""
|
||||
<div class="alert alert-info">%s</div>
|
||||
""" % _("No entries to display"))
|
||||
return t.render(Context())
|
||||
|
||||
def render_head(self, request):
|
||||
t = Template("""
|
||||
<table id="{{ tableid }}">
|
||||
{% include "common/table_head.html" %}
|
||||
</table>
|
||||
""")
|
||||
return t.render(Context({
|
||||
"table" : self, "tableid" : "%s_head" % self.tableid
|
||||
}))
|
||||
|
||||
def render_body(self, request):
|
||||
t = Template("""
|
||||
<table id="{{ tableid }}">
|
||||
{% include "common/table_body.html" %}
|
||||
</table>
|
||||
""")
|
||||
return t.render(Context({
|
||||
"table" : self, "tableid" : "%s_body" % self.tableid
|
||||
}))
|
||||
|
||||
|
||||
+2
-13
@@ -15,23 +15,12 @@ from django.utils import simplejson
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def _render(request, tpl, user_context):
|
||||
"""Custom rendering function
|
||||
def _render_to_string(request, tpl, user_context):
|
||||
"""Custom rendering function.
|
||||
|
||||
Just a wrapper which automatically adds a RequestContext instance
|
||||
(useful to use settings variables like STATIC_URL inside templates)
|
||||
"""
|
||||
return render_to_response(
|
||||
tpl, user_context,
|
||||
context_instance=template.RequestContext(request)
|
||||
)
|
||||
|
||||
|
||||
def _render_to_string(request, tpl, user_context):
|
||||
"""Custom rendering function
|
||||
|
||||
Same as _render.
|
||||
"""
|
||||
return render_to_string(tpl, user_context,
|
||||
context_instance=template.RequestContext(request))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user