简体   繁体   English

Django:如何将模型表单数据从一个页面传送到另一个页面,然后返回,而无需提交给DB?

[英]Django: How to carry model form data from one page to another, and back, without commiting to the DB?

[Preamble: Whereas I realize there may be simpler ways to do this (ie, just use Django built-in Admin, or use inlines to do all editing on one page, etc.), unfortunately, I am not in control of the designs, so I'm seeking help on how to work with what I've been tasked with implementing.] [序言:虽然我意识到可能有更简单的方法来做到这一点(即,只使用Django内置管理员,或使用内联在一个页面上进行所有编辑等),遗憾的是,我无法控制设计,所以我正在寻求如何处理我执行任务的帮助。

I have 2 models, Deck and Slide. 我有2个型号,Deck和Slide。 Slide has foreign key to Deck. Slide有Deck的外键。 (there is also an intermediate model--its a m2m relationship--but to simplify an already complex discussion, I'm going to pretend its a simpler many-to-one relationship.) (还有一个中间模型 - 它是一个m2m关系 - 但为了简化已经很复杂的讨论,我将假装它更简单的多对一关系。)

The interface i am implementing displays a page with a form to enter or edit Deck fields which also includes an embedded list of Slides in the Deck, with some fields (which I'm in the process of making text inputs) and also with an "edit" and a "remove" anchor link for each Slide. 我正在实现的界面显示一个页面,其中包含用于输入或编辑Deck字段的表单,其中还包括Deck中嵌入的Slides列表,其中包含一些字段(我正在进行文本输入)以及“为每张幻灯片编辑“和”删除“锚点链接。 (see img) If you click an "edit" link, it takes you to a new page with a detailed form to input all the information representing the content for the corresponding slide. (请参阅img)如果单击“编辑”链接,它将转到带有详细表单的新页面,以输入表示相应幻灯片内容的所有信息。 If you click submit in that form, it takes you back to the page for the deck. 如果单击该表单中的“提交”,则会返回到该卡片组的页面。

屏幕截图

As the title question proposes, I obviously don't want to commit any Deck or Slides to the DB until a user clicks Submit for the entire Deck, ie they can add or edit many slides in the interim and may decide to cancel the whole process. 正如标题问题所提出的那样,我显然不希望将任何Deck或Slides提交给DB,直到用户点击整个Deck的Submit,即他们可以在此期间添加或编辑许多幻灯片,并可能决定取消整个过程。

What is the best, cleanest way of doing this? 这样做的最好,最干净的方法是什么?

I've looked at Django's FormWizard class ( http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/ ), but seems to be geared towards a multi-step linear flow, not my situation. 我看过Django的FormWizard类( http://docs.djangoproject.com/en/dev/ref/contrib/formtools/form-wizard/ ),但似乎是面向多步线性流,而不是我的情况。

I already had to implement this for a demo, and I've gotten most of the way there by creating an inline FormSet for the Slides and a Form for the Deck, and then writing subclasses for my Forms that hide the form and the formset as I pass back and forth between the two pages. 我已经不得不为演示实现这个了,我通过为幻灯片创建一个内联FormSet和为Deck创建一个Form,然后为我的Forms创建隐藏表单和formset的子类来获得大部分内容。我在两页之间来回传递。 Here's some code demonstrating how I use a hidden form for the deck in the slide page: 这里有一些代码演示了我如何在幻灯片页面中使用隐藏的表单:

class DeckForm(ModelForm):
    class Meta:
        #stuff here

class HiddenDeckForm(DeckForm):
    def __init__(self, *args, **kwargs):
        super(DeckHiddenForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.iteritems():
            field.widget = field.hidden_widget()
            field.required = False

So in my views, every time I go to the slide form page, I generate a HiddenDeckForm from the POST data and pass it in, and then in my view going back to the deck page, I regenerate the DeckForm (not hidden subclass) from the POST data. 所以在我的观点中,每次进入幻灯片表单页面时,我都会从POST数据生成一个HiddenDeckForm并将其传入,然后在我的视图中返回到deck页面,我重新生成DeckForm(不是隐藏的子类) POST数据。 Not going to post all my Slide form code, since I'm basically asking whether there is a better way of doing it, but similarly, I have a HiddenSlideForm class, and pass a formset of those between my templates to save the state. 不会发布我的所有幻灯片表​​单代码,因为我基本上都在询问是否有更好的方法,但同样地,我有一个HiddenSlideForm类,并在我的模板之间传递一个formset来保存状态。

Then when the user clicks submit on the Deck page, the Deck form and Slides formset are all saved to the DB. 然后,当用户单击Deck页面上的submit时,Deck表单和Slides formset都将保存到DB。

It works, but is this a good way to do it? 它有效,但这是一个很好的方法吗? Its been a good bit of code, and I've really had to dig into some Django internals--feel's like I'm using things in a way they weren't designed to be used. 它是一个很好的代码,我真的不得不深入研究一些Django内部 - 感觉就像我使用的东西是他们没有被设计使用的方式。 Or is there already a more standard way of handling this scenario? 或者是否已经有更标准的方法来处理这种情况?

I'll post more code if its helpful. 如果它有用,我会发布更多代码。

Thanks for the help! 谢谢您的帮助!

PS As you can see, I'm implementing it in a jquery colorbox and using ajax for the transitions between the forms, but I am just using normal template/form rendering in my views and passing the rendered html back to the page with an ajax call . PS正如你所看到的,我正在jquery颜色框中实现它并使用ajax来处理表单之间的转换,但我只是在视图中使用普通模板/表单渲染并将渲染的html传回带有ajax的页面打电话。 . . guess I could do something with json, but strongly prefer to stick with passing a rendered template, as such an implementation could be used without ajax or javascript if desired. 我猜我可以用json做些什么,但强烈倾向于坚持传递一个渲染模板,因为这样的实现可以在没有ajax或javascript的情况下使用,如果需要的话。

Idea A: Store the uncommitted data in the session until everything is ready for commit. 想法A:将未提交的数据存储在会话中,直到所有内容都准备好提交。 Each form/roundtrip to the client just adds/updates the accumulating data. 到客户端的每个表单/往返只是添加/更新累积数据。 If they abandon it you only have crap lying around until the session is destroyed. 如果他们放弃它,你只会躺在周围,直到会议被破坏。 You can save pretty much anything to the session. 您可以在会话中保存几乎任何内容。

Idea B: Add a boolean to the database table which indicates when a row has been committed (eg: "is_active" or "is_pending"). 想法B:向数据库表添加一个布尔值,指示何时提交了一行(例如:“is_active”或“is_pending”)。 Means you never lose anything but a bit more of a nuisance to manage. 意味着你永远不会失去任何东西,但需要更多的麻烦来管理。

Having done the very similar requirement by working around the formset tools, I completely agree that going hoops and bounds to understand/customize the formset is totally not worth it. 通过使用formset工具完成了非常相似的要求,我完全同意,理解/自定义formset的箍和界限是完全不值得的。

For a screenshot like yours, I'd use just one form with all of the slides per deck. 对于像你这样的截图,我只使用一个表格,每张卡片都有所有幻灯片。 - Form, not formset. - 表格,而不是表格。

You should handle the slide "edit/delete/new" all in ajax requests that include the deck you create when someone creates a "new deck". 您应该在ajax请求中处理幻灯片“edit / delete / new”,其中包括您创建“新牌组”时创建的牌组。 And then in the "Deck Form", you only change the Deck properties like name and association. 然后在“Deck Form”中,您只更改Deck属性,如名称和关联。

Or, if you are inlined to do all new elements in the page itself without Ajax and creating new "Slide" objects, you can use the formset and save the deck and all associated slides. 或者,如果您内联在没有Ajax的情况下在页面中执行所有新元素并创建新的“幻灯片”对象,则可以使用formset并保存套牌和所有相关幻灯片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM