【问题标题】:Show all options in Django ManyToMany form以 Django ManyToMany 形式显示所有选项
【发布时间】:2015-07-26 01:02:29
【问题描述】:

我有两个 Django 模型,通过“通过”模型以多对多关系连接:

class Tag(Model):
     uuid = UUIDField(auto=True, version=4, primary_key=True)
     name = CharField(max_length=100)

class Agent(Model):
    uuid = UUIDField(auto=True, version=4, primary_key=True)
    tags = ManyToManyField(
        'Tag', blank=True, null=True, through='AgentTag')

class AgentTag(Model):
    agent = ForeignKey(Agent)
    tag = ForeignKey(Tag)
    experience = IntegerField()

我想创建一个表单,显示标签模型中的所有标签,以及让代理记录他/她在每个标签中的体验的下拉列表。如果用户之前已经更新了他们的体验,那么应该用这个来初始化表单。保存表单应该会更新 AgentTag “通过”表。

我需要什么类型的表单(或表单集?)来实现这一点?我不确定它应该是 AgentTag 的 ModelForm 还是定制的 Form。非常感谢有关如何解决此问题的一些帮助。

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    FormSet 在这里似乎不必要的复杂,尽管可能只是我没有使用 formset 的习惯。

    我想说,在你看来,你可以:

    1. 获取所有现有Tags 的列表。
    2. 为每个Tags 获取一个AgentTag,如果缺少则创建[0]。对于已经存在的那些,您将在他们的表格中预先填写经验。
    3. 遍历AgentTags,初始化一个ModelForm 每个都有唯一的prefix

    提交表单后,您的视图将遍历可用的AgentTags,根据发布的数据为每个表单构造一个表单,并保存生成的对象。

    您也可以考虑在用户修改体验下拉菜单时使用来自客户端的异步 HTTP (AJAX) 请求更新体验,但这会稍微复杂一些,不过您可能可以完全避开表单。

    [0] 实际上,根据您的要求,您似乎可以在保存新的Agent 后立即为每个Tag 创建一个AgentTag 实例(使用空的AgentTag.experience,您必须这样做可以为空),但这并不重要。

    【讨论】:

    • 谢谢!这是有道理的。有 215 个标签(我们通过 Javascript 显示/隐藏它们的不同部分),因此在 GET 和 POST 上实例化许多表单感觉就像很多服务器工作。我很想将数据结构的当前状态添加到上下文中,手动呈现复选框,然后从 POST 响应更新模型,完全绕过 Django 表单。如果您觉得这是个坏主意,请告诉我。
    • 虽然我不认为实例化 215 个表单一定很麻烦(如果您避免在循环中进行任何数据库查询),但如果您只需要显示一个表单,那么完全放弃表单绝对是有意义的每个标签的体验选择器。它还可以让选择器更容易定制——无需深入研究表单小部件和其他东西。
    猜你喜欢
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多