使用额外条目拖放formset的排序

时间:2010-01-03 03:09:58

标签: javascript jquery python django

我一直在寻找一种方法,允许用户轻松更改表单集中条目的顺序。我发现a StackOverflow question解决了这个问题,接受的答案引用了Django Snippet,它使用JQuery工具来拖放条目。这很漂亮很酷,但我有'额外'条目的问题。如果修改了“额外”条目然后拖动,我会在提交时收到错误:

(1048, "Column 'order' cannot be null")

我相信Django会将'额外'条目分开,因为它们必须插入而不是更新。所以重新排序可能会让事情变得混乱。有没有办法使这项工作,还是有其他建议重新排序和/或添加新条目?

编辑:添加了一些相关的代码摘录。我正在管理员中尝试这个,正如代码段所示。不过,我最终会把它放在我自己的页面中。

models.py:

class Section(models.Model):
    section_id = models.AutoField(primary_key=True)
    section_name = models.CharField(max_length=135)
    score_order = models.IntegerField()
    def __unicode__(self):
      return self.section_name
    class Meta:
        db_table = u'section'
        ordering = [u"score_order"]

class Chair(models.Model):
    chair_id = models.AutoField(primary_key=True)
    member = models.ForeignKey(Member, null=True, blank=True,
      limit_choices_to={'current_member': True})
    section = models.ForeignKey(Section)
    description = models.CharField(max_length=135)
    order = models.IntegerField(blank=True, null=True)
    def __unicode__(self):
      return "%s - %s" % (self.description, self.member)
    class Meta:
        db_table = u'chair'
        ordering = (u'section', u'order')

admin.py

class SectionForm(forms.ModelForm):
    model = Section
    class Media:
        js = (
            '/scripts/jquery.js',
            '/scripts/ui.core.js',
            '/scripts/ui.sortable.js',
            '/scripts/section-sort.js',
        )

class ChairInline(admin.StackedInline):
    model = Chair

admin.site.register(Section,
                    inlines = [ChairInline],
                    form = SectionForm,
)

2 个答案:

答案 0 :(得分:2)

我找到了自己的解决方案。该片段为具有非空主键值的每一行设置顺序。但额外的行有一个空的主键,我相信他们必须留空,让Django知道它们是要插入而不是更新。我修改了函数以检查其他字段是否为空(幸运的是,我只有一对)以及主键:

jQuery(function($) {
    $('div.inline-group').sortable({
        items: 'div.inline-related',
        handle: 'h3:first',
        update: function() {
            $(this).find('div.inline-related').each(function(i) {
                if ($(this).find('input[id$=chair_id]').val() ||
                  $(this).find('select[id$=member]').val() ||
                      $(this).find('select[id$=description]').val()) {
                    $(this).find('input[id$=order]').val(i+1);
                }
            });
        }
    });
    $('div.inline-related h3').css('cursor', 'move');
    $('div.inline-related').find('input[id$=order]').parent('div').hide();
});

这对我有用。我可以通过向表单中添加隐藏字段来改进它,只要行上的任何字段被修改就会被设置。但在这一点上我仍然是一个jQuery n00b,所以这样做。如果有人有更好的想法,请随时发表评论或添加其他答案。

答案 1 :(得分:1)

我在其中一个应用中执行可排序的formset。我使用这个jQuery拖放插件:

http://www.isocra.com/2008/02/table-drag-and-drop-jquery-plugin/

我将插件的onDrop事件绑定到一个重置所有“order”字段值的函数。

此外,我将初始数据传递给formset,因此formset的额外“order”字段总是有一个值,如果没有可用的javascript - 用户将无法重新排序行,但他们可以编辑并在没有您描述的空错误的情况下发布更改。