2014-01-06 61 views
0

我想将ORM控件公开给我的用户。我不是说我希望他们能够将部分代码添加到代码中,我的意思是我实际上允许他们编写django代码。我只需要允许特定的模型,并且只允许获取数据(不添加或更改任何内容)。这将会像控制台一样,每一行都会被执行(有点像ipython笔记本),并且返回的数据(如果它是一个QuerySet对象)将被显示在某种表格中。允许管理员通过视图控制Django ORM

此功能只适用于我的超级用户管理员,因此不会成为安全问题。最好的办法是什么(如果可能的话)?

更新

也许我应该给一些背景这里使用目的。请参阅我已经构建了一个收集和保存统计信息的应用程序。我的用户有很多我为他们构建的过滤器,但他们不断要求越来越多的灵活性,有时候他们需要过滤一些非常具体的东西,而且这只是一次性的东西,所以我不能一直添加越来越多的特征。

现在我的超级用户知道一个小蟒蛇,并且我明白了,也许我可以给他们某种方式来自己过滤。这个想法是他们将能够保存查询并命名它们,然后将这些自定义过滤器添加到主站点上的列表中。

它的工作方式是获取包含所有对象的QuerySet对象,它们可以使用预定义命令列表进行过滤。运行该命令后,服务器将对其进行评估,查找错误或禁止的代码,然后才会运行该代码。但我猜我不能只在生产服务器上使用eval(),现在可以吗?那么还有其他一些方法吗?

+0

没有好的方法来做到这一点。 – ThiefMaster

+1

也许Django管理第二个数据库。 –

回答

1

添加文件添加用户使用此外壳

useradd -s /usr/local/sbin/djshell -g www-data [more options] superdjangoadmin 

通过ssh登录允许。用户直接连接到django外壳,类型from app.models import *,这就是你所需要的。

从此shell中,用户可以中断可访问的数据。您必须确保所有数据都是只读的。 也许运行这与settings.py的副本与DATABASES setuped用只读用户名。

伪代码的

定制外壳

#imports 
command = input()#expecting "filter(...).last()" or so 
cleanup(command) #remove ";", "eval()", escape parameter values, strip 
command = "MyModel.objects." + command 
try: 
    result = eval(command) 
    prettyprint(result) 

except Exception as e: 
    print get_traceback()   
    print e.message 
+0

谢谢如果我想实际给它们shell控制,这是一个很好的答案,但这不完全是我需要的。我希望他们对基本过滤功能进行一些简化以允许自定义查询创建。 – yuvi

+0

@yuvi写定制shell =) – eri

+0

我自己的定制shell是?不是一个坏主意。我会考虑它 – yuvi

1

我想其实让他们写的Django代码

这意味着给某些用户访问编写的Django,并通过扩展Python和代码。在管理员用户终端不能访问现场机器上的代码的情况下,这是不可能的。如果您确实授予终端对代码的访问权限,那么是一个安全问题,因为简单的语法错误可能会导致整个网站停止运行。

此外,如果你这样做,用户每次改变都需要对数据库进行重新同步,并有他们可能会做出改变到syncdb甚至South玩不转这意味着你的数据模型的真正危险是无法挽回的,网站无法正常运作。

重新设计您的应用程序,以便通过更改对象的实例而不是对象代码本身来实现灵活性。在服务器/usr/local/sbin/djshell

#!/bin/sh 
cd /path/to/project/ 
/path/to/python /path/to/project/manage.py shell #or "dbshell" or custom interactive task 

+0

谢谢。虽然有一些笔记 - 1.首先,当我说django代码时,我只是指它的抽象。他们不会自己获取模型,但是他们可以过滤掉MyModel.objects.all()的QuerySet对象(并且没有其他)2.我只打算公开一小部分API,并在运行之前用白名单自己评估它3.我没有看到错误处理的问题,因为我可以扫描这些,并且不会返回任何东西(或以文本格式返回回溯) – yuvi

0

如果管理员知道SQL - 给他们phpmyadmin具有只读privelegies。

+0

他们不,但。谢谢 – yuvi

0

搞乱了一下后,我意识到我正在寻找比我想象的更简单的事情。这里有一个如何这看起来一个快速的想法(项目是两个领域,电子邮件地址和名称的测试模型):

服务器端:

def qs_eval(request): 
    items = Item.objects.all() 
    code = '' 
    if request.method == 'GET': 
     code = request.GET['code'] 
     cleaned = map(lambda x: x.strip(), code.split(',')) 
     commands = dict([x.split('=') for x in cleaned if x]) 
     items = items.filter(**commands)   

    return render_to_response('qs_eval.html', {'items': items, 'code': code}) 

HTML:

<form> 
    <input type='text' name='code' value='{{ code }}' /> 
    <button cls='btn'>send!</button> 
</form> 

<table class='table'> 
    <thead> 
    <tr> 
     <th>name</th> 
     <th>email</th> 
    </tr> 
    </thead> 

    <tbody> 
    {% for i in items %} 
     <tr> 
      <td>{{ i.name }}</td> 
      <td>{{ i.email }}</td> 
     </tr> 
    {% endfor %} 
    </tbody> 
</table> 

显然,有这里没有错误处理,我只允许过滤,但很容易扩展到其他功能,如排除和更多,并pythonically检查代码的任何禁止等。

无论如何,这是我最终做的。我仍然会把@ eri的建议标记为答案,看看如何真正完成控制台类型的控制,这可能是正确的方向

+0

它不适合复杂的查询 – eri

+0

我从来没有说过我需要复杂的查询 – yuvi

+0

限制和聚合通常是需要的 – eri

相关问题