import inspect
import logging
import os
import os.path
import sys
from django.conf import settings
from django.http import HttpRequest
def obtain_request():
ancestors = inspect.getouterframes(inspect.currentframe())
for frame_record in ancestors:
frame = frame_record[0]
if 'request' in frame.f_locals:
req = frame.f_locals['request']
if isinstance(req, HttpRequest):
return req
def get_logger(request=None):
if request is None:
request = obtain_request()
stack = inspect.stack()
logger_name = '%s.%s' % (stack[1][0].f_globals['__name__'], stack[1][3])
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG)
def addLogger(x):
x.setLevel(logging.DEBUG)
logger.addHandler(x)
server = request.META.get('wsgi.file_wrapper', None) if request else None
if server is None or server.__module__ == 'django.core.servers.basehttp':
addLogger(logging.StreamHandler(sys.stdout))
else:
addLogger(logging.StreamHandler(request.META['wsgi.errors']))
log_file = os.path.join(
os.path.abspath(settings.PROJECT_ROOT),
'logs', '%s.log' % logger_name)
log_dir = os.path.dirname(log_file)
if not os.path.exists(log_dir):
os.mkdirs(log_dir)
addLogger(logging.FileHandler(log_file))
return logger
Пероксид на Джанге.
Жаба на метле
03.03.12
logger
25.10.11
Uploadify на Mac OS X
Говорят, что у Mac OS X есть какие-то проблемы с Flash. Или наоборот, что у Flash есть какие-то проблемы с Mac OS X. В общем, есть между ними какие-то трения. Я лично столкнулся с чем-то таким, используя Uploadify. Этот плагин jQuery вносит метод uploadify, который принимает объект опций, среди которых есть scriptData. scriptData - объект, свойства которого будут добавлены к POSTу, когда flash-часть uploadify начнет загружать файл на сервер. В теории и документации вы увидите все, что передали в scriptData, в request.POST (если, конечно, используете Django).
На самом деле все не так. На Mac OS X вы увидите только первое свойство объекта scriptData. Так, если scriptData: {'size': '160x160', 'crop': true}, то вы request.POST будет только size. Обойти это можно так. Вместо {'scriptData': {'foo': 'bar', 'bar': 'foo'} }надо передать {'auto': false, 'onSelect': function(){ $x.uploadifySettings({'foo': 'bar', 'bar': 'foo'}); $x.uploadifyUpload();}}. Здесь $x - тот же объекта, метод котрого uploadify() вы вызываете. Так работает.
Но это не вся правда. в request.POST будет элемент 'foo' и элемент 'amp;bar'. Ну это просто:
if 'amp;crop' in request.POST:
request.POST['crop'] = request.POST['amp;crop']
Почему так - не знаю. Но надеюсь, что моя небольшая находка сэкономит кому-то (мне) немного времени.
18.10.11
Важность правильных названий переменных
Я никак не мог запомнить кто из аргументов функции, передаваемой reduce, аккумулятор, а кто очередной элемент обрабатываемой последовательности. Теперь-то я понимаю, что это не только потому, что я немного пустоголовый, но и потому, что в официальной документации Python в примере для функции reduce эти аргументы называются x и y.
Но сегодня я прочел заметку про underscore.js некоего кого-то и буду помнить, что аккумулятор - первый аргумент. Просто в примере использования reduce автор заметки назвал аргументы передаваемой в reduce функции sum и n. Вот так просто.
16.10.11
node.js-like next
Есть у нас профили. Отдельный профиль доступен по пути, который соответствует '^(\w+)/$'. Хорошо. Прошло полгода, появилась новая сущность (НС). Попросили, чтобы отдельная НС была доступна по пути, который соответствует '^(\w+)/$'. Для простоты и красоты.
Можно в первой вьюшке генерировать 404, если по слагу не находится профиль, ловить 404 тут же и вызывать вторую вьюшку, передавая туда слаг.
def profile_detail(request, slug):
try:
profile = get_object_or_404(Profile, slug=slug)
except Profile.DoesNotExist:
return another_detail(request, slug)
else:
...
В node.js фреймворке Express можно передать контроль следующему обработчику пути. Вот бы Джанге что-то такое.
30.10.09
load_object - пара к render_object
from django.template import Library, Node, TemplateSyntaxError
from django.contrib.contenttypes.models import ContentType
register = Library()
class LoadObjectNode(Node):
def __init__(self, app_label, model, pk, name, nodelist):
self.app_label = app_label
self.model = model
self.pk = pk
self.name = name
self.nodelist = nodelist
def __repr__(self):
return "<LoadObjectNode>"
def render(self, context):
app_label = self.app_label.resolve(context)
model = self.model.resolve(context)
pk = self.pk.resolve(context)
try:
content_type = ContentType.objects.get(
app_label=app_label, model=model)
except ContentType.DoesNotExist:
return ''
else:
klass = content_type.model_class()
try:
val = klass._default_manager.get(pk=pk)
except (klass.DoesNotExist, klass.MultipleObjectsReturned):
return ''
else:
context.push()
context[self.name] = val
output = self.nodelist.render(context)
context.pop()
return output
def do_load_object(parser, token):
"""
Used get an object by content type app_name and model
attributes and object primary key and inject it into context.
Usage:
{% load_object app_label model pk as name %}
{{ varname }}
{% endload_object %}
Exceptionally usful in conjunction with render_object template tag
http://www.djangosnippets.org/snippets/1745/
"""
bits = list(token.split_contents())
if len(bits) != 6 or bits[-2] != 'as':
raise TemplateSyntaxError(
"%r expected format is 'load_object app_label model pk as name'" %
bits[0])
app_label = parser.compile_filter(bits[1])
model = parser.compile_filter(bits[2])
pk = parser.compile_filter(bits[3])
name = bits[5]
nodelist = parser.parse(('endload_object', ))
parser.delete_first_token()
return LoadObjectNode(app_label, model, pk, name, nodelist)
do_load_object = register.tag('load_object', do_load_object)
29.10.09
render_object
- "render/[position]/[app_label]_[model_name].html"
- "render/[position]/default.html"
- "render/[app_label]_[model_name].html"
- "render/default.html"
28.10.09
Орднунг defaulttags.py
def do_xxx():
#или так:
def do_xxx():
...
register.tag('xxx', do_xxx)0
def do_xxx():
...
do_xxx = register.tag('xxx', do_xxx)