我正在寻找与Semantic MediaWiki提供的功能模糊不清的功能。简而言之,我希望用户在任意文本字段中能够执行以下操作(我在编写标记时)。
*大家好,不要忘记我们的土地上有[[:: AfricanSwallow.count]]非洲燕子。
*你知道欧洲燕子哈利带着[[:: EuropeanSwallow.get(姓名="哈利")。coconuts.count]]椰子回来了吗?
除了这些功能之外,我还希望能够自动完成内联 - 也许是在用户开始输入时。
我可以做所有这些事情,但我希望他们中的一些或全部已经完成。不管是不是这样的话?
答案 0 :(得分:1)
我认为这样的事情是可行的,但要使其普及(允许对ORM进行完全只读访问)将很难以安全的方式进行。
以下是一些想法:
将操作限制为自定义管理器类上的一组预定义的显式标记方法。例如:
from django.db import models
class MarkupAccessManager(models.Manager):
def count(self):
return super(MarkupAccessManager, self).count()
count.expose_to_markup = True
class AfricanSwallow(models.Model):
objects = MarkupAccessManager()
要引用标记中的模型,您可以利用django.contrib.contenttypes
框架,标记可以采用以下格式:app_label.model_name action
或app_label.model_name action arg1 arg2
。
根据您选择的标记语言,您可以使用自定义标记(如果语言提供),Django模板标记或普通正则表达式。获得标记的内容后,可以使用引用方法的输出替换它:
from django.contrib.contenttypes.models import ContentType
def replace_tag(tag):
"""
'birds.africanswallow count' => birds.models.AfricanSwallow.objects.count()
"""
bits = tag.split()
model_ref = bits[0]
action = bits[1]
args = bits[2:]
try:
ct = ContentType.objects.get_by_natural_key(*model_ref.split('.'))
except ContentType.DoesNotExist:
return 'Invalid model reference.'
model = ct.model_class()
method = getattr(model._base_manager, action, None)
if not method or not method.expose_to_markup:
return 'Invalid action.'
return method(*args)
要提供自动填充功能,这些内容可帮助您构建所有可用选项的列表:
from django.db.models.loading import get_models
from django.contrib.contenttypes.models import ContentType
def model_refs():
for model in get_models():
if isinstance(model._base_manager, MarkupAccessManager):
ct = ContentType.objects.get_for_model(model)
yield '%s.%s' % (ct.app_label, ct.model)
def actions():
for attr_name in dir(MarkupAccessManager):
attr = getattr(MarkupAccessManager, attr_name)
if attr.expose_to_markup:
yield attr.__name__
我没有测试过代码。希望这有点帮助。
答案 1 :(得分:0)
最优雅的解决方案是创建一个编译器,它只允许执行certian指令。了解更多@ http://en.wikibooks.org/wiki/Compiler_Construction
另一种方法是使用 exec(),但应该避免使用,因为它会给您的应用带来很多安全问题。你总是可以尝试先解析字符串(有效的语法)但它仍然是一个可能的漏洞。