在用户输入的文本中链接到django模型并从中获取数据

时间:2011-04-07 14:47:05

标签: django django-models markdown semantic-markup

我正在寻找与Semantic MediaWiki提供的功能模糊不清的功能。简而言之,我希望用户在任意文本字段中能够执行以下操作(我在编写标记时)。

*大家好,不要忘记我们的土地上有[[:: AfricanSwallow.count]]非洲燕子。

*你知道欧洲燕子哈利带着[[:: EuropeanSwallow.get(姓名="哈利")。coconuts.count]]椰子回来了吗?

除了这些功能之外,我还希望能够自动完成内联 - 也许是在用户开始输入时。

我可以做所有这些事情,但我希望他们中的一些或全部已经完成。不管是不是这样的话?

2 个答案:

答案 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 actionapp_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(),但应该避免使用,因为它会给您的应用带来很多安全问题。你总是可以尝试先解析字符串(有效的语法)但它仍然是一个可能的漏洞。