自定义金字塔FormAlchemy表单

2 投票
1 回答
770 浏览
提问于 2025-04-17 05:13

我在使用pyramid_formalchemy创建自定义表单时遇到了一些问题。我怀疑这个包可能有bug,想确认一下我是不是哪里搞错了。我的设置大致是这样的:

def includeme(config):
    config.include('pyramid_formalchemy')
    # Adding the jquery libraries
    config.include('fa.jquery')
    # Adding the package specific routes
    config.include('myapp.web.formalchemy.faroutes')

    config.formalchemy_admin('admin',
                             models=[User],
                             forms=faforms,
                             session_factory=session,
                             view='fa.jquery.pyramid.ModelView',
                             factory='myapp.model.RootFactory')

    config.formalchemy_model('user',
                             model='myapp.model.user.User',
                             session_factory=session,
                             view='fa.jquery.pyramid.ModelView',
                             factory='myapp.model.RootFactory')

faforms是一个模块,里面包含了我的自定义表单:

from myapp.model.user import User

from formalchemy import FieldSet
from formalchemy import Grid

class UserFieldSet(FieldSet):
    def __init__(self):
        FieldSet.__init__(self, User)
        self.configure()

class UserGrid(Grid):
    def __init__(self):
        Grid.__init__(self, User)
        self.configure()

如果我把上面那两个类注释掉,formalchemy就能正常工作。我可以查看用户信息,也可以编辑它们。

但是一旦我把这两个类放进去,就会出现问题。问题在于pyramid_formalchemy会从模块的命名空间中抓取UserGrid和UserFieldSet,然后试图把它们当作已经实例化的类来使用。这就导致了错误。另一方面,如果pyramid_formalchemy找不到这些类,它会动态创建这些类并实例化它们。我认为出问题的代码在pyramid_formalchemy/views.py的第236行,从get_grid()函数开始:

def get_grid(self):
    """return a Grid object"""
    request = self.request
    model_name = request.model_name
    form_name = '%sGrid' % model_name
    if hasattr(request.forms, form_name):
        g = getattr(request.forms, form_name)  <-- g is a class type not an
        g.engine = g.engine or self.engine     <-- instance!
        g.readonly = True                      <-- why is it not instantiated?
        g._request = self.request
        self.update_grid(g)
        return g
    model = self.context.get_model()           <-- UserGrid not found in faforms 
    grid = self.grid_class(model)              <-- module.
    grid.engine = self.engine                  <-- so a Grid is instantiated
    if not isinstance(request.forms, list):
        # add default grid to form module eg: caching
        setattr(request.forms, form_name, grid)
    grid = grid.copy()
    grid._request = self.request
    self.update_grid(grid)
    return grid

在这里你可以看到,如果没有找到匹配的网格(或字段集),它会被实例化;但如果找到了,类类型会直接被使用,但实际上并没有被实例化。

你有什么想法吗?我是不是哪里设置错了?

基本上,我在使用CSRF令牌,所以我需要自定义我的表单,以便从会话中获取这些令牌。

谢谢。

1 个回答

5

pyramid_formalchemy 对你如何设置表单文件有一些基本的假设,这些假设大多没有详细说明。以下是我遇到的一些问题和解决方法……

  1. 比如说,如果你有一个叫 User 的模型,那么你需要有一个叫 UserFieldSet 的字段集。

  2. UserFieldSet 必须是一个实例,而不是一个类。

  3. 在导入时要小心,否则会破坏 pyramid_formalchemy 的一些假设。如果你有一个模型类 User,应该导入 User 的包,而不是直接导入 User 类本身。然后在引用这个类时,要在前面加上包的名字。

下面是一个使用以上三点的工作示例。

from myapp.model import user

from formalchemy import Field
from formalchemy import FieldSet
from formalchemy import Grid

UserFieldSet = FieldSet(user.User)
UserFieldSet.configure()

UserGrid = Grid(user.User)
UserGrid.configure()

你也可以去 formalchemy 组 发帖获取更多信息。

撰写回答