【发布时间】:2014-08-04 23:16:56
【问题描述】:
假设我有一组简单的 Django 模型,通过 ForeignKey 关联:
class Author(models.Model):
name = models.CharField('Name', max_length=50)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField('Title', max_length=50)
rank = models.IntegerField('Rank')
现在在我的模板中,我想创建一个用户界面,其中有两个并排的<ol> 列表,每个列表代表给定作者的书籍列表,按其等级排序,并且在 @ 中有一个表单用于书籍987654324@ 节点。因此,整个页面由一个 Author 表单集组成,每个表单集都由一个内联 Book 表单集组成。希望这很清楚......
现在有了一些花哨的 javascript/jQuery,我允许用户做两件事:1)她可以在其 <ol> 中拖放一个 Book 表单来设置它的 rank,以及 2)她可以拖放 -然后将一本书从一个<ol> 放到另一个<ol>,目的是更改其作者。
从 Django 的角度来看,form me 完成任务 1 绝对没有问题。formset 提交,数据保存,Django 不知道这种方法和用户输入不同的区别当然,书籍在输入文本字段中排名。
但是,在我看来,完成任务 2 有点棘手。如果我将 Book 表单从一个 Author 列表拖放到另一个,然后使用一些更花哨的 javascript 来更新其输入类 id 和名称(例如id_1-book-0-title --> id_2-book-0-title),以及更新Book formset Management 表单的 TOTAL_FORMS 和 INITIAL_FORMS 以反映每行中 Book 表单的新数量,然后事情就不太正常了。
Django 将列表中拖动的表单视为一个新表单,并在数据库中创建一个真正的新书(如果你有唯一的字段,因为这本书已经在数据库中,这是有问题的)。至于 oldlist 中缺少此表单,则不会发送表单 DELETE,因此 Django 当然不会最终删除旧对象。如果没有任何唯一字段,结果是您在数据库中获得两份图书副本,现在每个作者的列表中都有一份。使用某种 Book 模型的唯一字段(例如序列号),您只会遇到验证错误。
有谁知道正确的设置方法是什么?
编辑:这是我目前所拥有的粗略的view:
def managerView(request):
if request.method == "POST":
author_formset = AuthorFormSet(request.POST, prefix='author')
pairs =[]
for authorform in author_formset:
author=authorform.instance
tempDict={}
tempDict['authorform'] =authorform
tempDict['bookformset'] = BookFormSet(request.POST, prefix=str(author.pk)+'-book', instance=author)
pairs.append(tempDict)
if author_formset.is_valid() and all([pair['bookformset'].is_valid() for pair in pairs]):
author_formset.save()
for pair in pairs:
author=pair['authorform'].instance
#For this author, delete all current books, then repopulate
#from forms in book list that came from request.
old_book_pks = set([book.pk for book in author.books.all()])
new_book_pks = set([bform.instance.pk for bform in pair['bookformset'].forms])
pks_for_trash = old_book_pks - new_book_pks
if len(pair['bookformset'].forms): pair['bookformset'].save()
return HttpResponseRedirect(reverse('admin:index'))
else:
author_formset = AuthorFormSet(prefix='author', queryset=Author.objects.order_by('rank'))
pairs=[]
for f in author_formset:
author=f.instance
#prefix the different book formsets like '1-book' etc
pairs.append({'authorform':f, 'bookformset': BookFormSet(prefix=str(author.pk)+'-book',instance=author)})
myContext= {'authorformset': author_formset, 'pairs':pairs, 'request': request}
return myContext
现在是表单集:
AuthorFormSet = modelformset_factory(Author, extra=0)
BookFormSet = inlineformset_factory(Author, Book, form=BookForm, extra=0, formset=BaseBookFormSet)
除了一些自定义清理之外,BookForm 和 BaseBookFormSet 中没有发生太多事情,所以我暂时不会包括它们,除非有人认为它们有用。
【问题讨论】:
标签: django forms foreign-keys django-forms inline-formset