2013-11-26 16 views
1

嵌套形式我的功能,我需要實現與以下車型和Django

class Publisher(models.Model): 
    name = models.CharField(max_length=256) 
    address1 = models.CharField(max_length=256) 
    address2 = models.CharField(max_length=256) 
    city = models.CharField(max_length=256) 

class Author(models.Model): 
    publisher = models.ForeignKey(Publisher) 
    name = models.CharField(max_length=256) 
    address = models.CharField(max_length=256) 

class Book(models.Model): 
    author = models.ForeignKey(Author) 
    name = models.CharField(max_length=256) 
    price = models.FloatField() 

forms.py

class PublisherForm(ModelForm): 
    class Meta: 
     model = Publisher 

    def __init__(self, *args, **kwargs): 

     super(PublisherForm, self).__init__(*args, **kwargs) 
     self.fields['name'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Publisher Name', 'autofocus':'autofocus'} 
     self.fields['address'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Publisher Address '} 


class AuthorForm(ModelForm): 
    class Meta: 
     model = Author 
     exclude = ('publisher',)  

    def __init__(self, *args, **kwargs): 

     super(AuthorForm, self).__init__(*args, **kwargs) 
     self.fields['name'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Author Name'} 
     self.fields['address'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Author Address'} 

class BookForm(ModelForm): 
    class Meta: 
     model = Book 
     exclude = ('author',)  

    def __init__(self, *args, **kwargs): 

     super(BookForm, self).__init__(*args, **kwargs) 
     self.fields['name'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Book Name'} 
     self.fields['price'].widget.attrs = {'id':'inputIcon', 'class':'input-block', 'placeholder':'Book Price'} 
與上述型號的形式

所以嵌套Django表單,我需要在同一屏幕上動態創建表單,如下面的UI屏幕

enter image description here

因此,從上面的屏幕中,我們可以觀察到所有三個模型窗體應該顯示在同一頁面上。

1. The publisher may have many authors 
2. Each author may have many books 

您也可以從設計觀察,我們有

1.Add Another Author - Adding Multiple Authors 
2.Add Book - Adding multiple books for Author 

2.兩個按鈕添加圖書

當我們單擊添加圖書,新的圖書形式應該是創建截圖爲

1.添加另一個作者

當我們點擊Add another author按鈕,一個新的作者記錄應顯示他可以能夠爲筆者上面一樣通過點擊Add Book

新增多本圖書。如果我們只有兩個型號A和B,如果B已經ForeignKey到A,那麼我們可以能夠通過usign Django的formsets or inline_formsets or model_formsets來實現這一目標functionlaity,但這裏在上面,我們應該能夠

  1. 添加嵌套(多個)Book形式爲Author
  2. 添加巢ED(多)Author形式爲出版商

那麼如何實現上述功能呢?,我尋覓了很多,但不能能找出上述東西

+0

通過'字符替換'Charfield'你的代碼示例 – juliocesar

回答

4

這可以這樣做在創建發佈者的視角下玩inlineformsets,返回作者和書籍表單集(爲每個表單使用不同的前綴參數),然後使用javascript爲書和作者添加新表單。

波紋管是我爲您編寫的基本樣本。

的技巧是使用JavaScript來生成與相關父作者動態表單模板前綴書表單集(books_formset_0books_formset_1,...),然後透過形式,遍歷每個作者找到相關book_formset 。

運行和測試此代碼的完整django項目可以下載here

重要提示:下面的代碼還沒有被優化,而不是使用一些標準的工具,如JS模板,AJAX等,但它的工作原理,並演示瞭如何解決這個問題。

template.py:

<script type="text/javascript" src="{{ STATIC_URL }}js/jquery.js"></script> 
<script type="text/javascript"> 
    $(function() { 
     $('form').delegate('.btn_add_book', 'click', function() { 
      var $this = $(this) 
      var author_ptr = $this.attr('id').split('-')[1] 
      var $total_author_books = $(':input[name=books_formset_' + author_ptr + '-TOTAL_FORMS]'); 
      var author_book_form_count = parseInt($total_author_books.val()) 
      $total_author_books.val(author_book_form_count + 1) 

      var $new_book_form = $('<fieldset class="author_book_form">' + 
       '<legend>Book</legend>' + 
       '<p>' + 
       '<label for="id_books_formset_' + author_ptr + '-' + author_book_form_count + '-name">Name:</label>' + 
       '<input id="id_books_formset_' + author_ptr + '-' + author_book_form_count + '-name" maxlength="256" name="books_formset_' + author_ptr + '-' + author_book_form_count + '-name" type="text" />' + 
       '<input id="id_books_formset_' + author_ptr + '-' + author_book_form_count + '-author" name="books_formset_' + author_ptr + '-' + author_book_form_count + '-author" type="hidden" />' + 
       '<input id="id_books_formset_' + author_ptr + '-' + author_book_form_count + '-id" name="books_formset_' + author_ptr + '-' + author_book_form_count + '-id" type="hidden" />' + 
       '</p>' + 
       '</fieldset>' 
      ) 

      $this.parents('.author_form').find('.author_books').prepend($new_book_form) 
     }) 

     $('form').delegate('#btn_add_author', 'click', function() { 
      var $total_authors = $(':input[name=authors_formset-TOTAL_FORMS]'); 
      author_form_count = parseInt($total_authors.val()) 
      $total_authors.val(author_form_count + 1) 

      book_form = '<fieldset class="author_book_form">' + 
       '<legend>Book</legend>' + 
       '<p>' + 
       '<label for="id_books_formset_' + author_form_count + '-0-name">Name:</label>' + 
       '<input id="id_books_formset_' + author_form_count + '-0-name" maxlength="256" name="books_formset_' + author_form_count + '-0-name" type="text" />' + 
       '<input id="id_books_formset_' + author_form_count + '-0-author" name="books_formset_' + author_form_count + '-0-author" type="hidden" />' + 
       '<input id="id_books_formset_' + author_form_count + '-0-id" name="books_formset_' + author_form_count + '-0-id" type="hidden" />' + 
       '</p>' + 
       '</fieldset>'; 

      $new_author_form = $(
       '<fieldset class="author_form">' + 
       '<legend>Author</legend>' + 
       '<p>' + 
       '<label for="id_authors_formset-' + author_form_count + '-name">Name:</label>' + 
       '<input id="id_authors_formset-' + author_form_count + '-name" maxlength="256" name="authors_formset-' + author_form_count + '-name" type="text" />' + 
       '<input id="id_authors_formset-' + author_form_count + '-publisher" name="authors_formset-' + author_form_count + '-publisher" type="hidden" />' + 
       '<input id="id_authors_formset-' + author_form_count + '-id" name="authors_formset-' + author_form_count + '-id" type="hidden" />' + 
       '</p>' + 
       '<p><input type="button" value="Add Book" class="btn_add_book" id="author-' + author_form_count + '"/></p>' + 
       '<div class="author_books">' + 
       '<input id="id_books_formset_' + author_form_count + '-TOTAL_FORMS" name="books_formset_' + author_form_count + '-TOTAL_FORMS" type="hidden" value="1" />' + 
       '<input id="id_books_formset_' + author_form_count + '-INITIAL_FORMS" name="books_formset_' + author_form_count + '-INITIAL_FORMS" type="hidden" value="0" />' + 
       '<input id="id_books_formset_' + author_form_count + '-MAX_NUM_FORMS" name="books_formset_' + author_form_count + '-MAX_NUM_FORMS" type="hidden" value="1000" />' + 
       book_form + 
       '</div >' + 
       '</fieldset >' 
      ) 

      $('#authors').prepend($new_author_form) 
     }) 
    }) 
</script> 
<h1>Add Publisher</h1> 
<form action="" method="post"> 
    {% csrf_token %} 
    {{ form.as_p }} 

    <p><input type="button" id="btn_add_author" value="Add another author"/></p> 

    <div id="authors"> 
     {{ authors_formset.management_form }} 
     {% for form in authors_formset %} 
      <fieldset class="author_form"> 
       <legend>Author</legend> 
       {{ form.as_p }} 
       <p><input type="button" value="Add Book" class="btn_add_book" id="author-{{ forloop.counter0 }}"/></p> 

       <div class="author_books"> 
        {{ books_formset.management_form }} 
        {% for form in books_formset %} 
         <fieldset class="author_book_form"> 
          <legend>Book</legend> 
          {{ form.as_p }} 
         </fieldset> 
        {% endfor %} 
       </div> 
      </fieldset> 
     {% endfor %} 
    </div> 
    <p><input type="submit" value="Save"></p> 
</form> 

forms.py:

AuthorInlineFormSet = inlineformset_factory(Publisher, Author, extra=1, can_delete=False) 
BookInlineFormSet = inlineformset_factory(Author, Book, extra=1, can_delete=False) 

views.py:

class PublisherCreateView(CreateView): 
    model = Publisher 

    def form_valid(self, form): 
     result = super(PublisherCreateView, self).form_valid(form) 

     authors_formset = AuthorInlineFormSet(form.data, instance=self.object, prefix='authors_formset') 
     if authors_formset.is_valid(): 
      authors = authors_formset.save() 

     authors_count = 0 
     for author in authors: 
      books_formset = BookInlineFormSet(form.data, instance=author, prefix='books_formset_%s' % authors_count) 
      if books_formset.is_valid(): 
       books_formset.save() 
      authors_count += 1 

     return result 

    def get_context_data(self, **kwargs): 
     context = super(PublisherCreateView, self).get_context_data(**kwargs) 
     context['authors_formset'] = AuthorInlineFormSet(prefix='authors_formset') 
     context['books_formset'] = BookInlineFormSet(prefix='books_formset_0') 
     return context 
+0

BRB中的'ForeignKey'字段和Foreignkey'例如 – juliocesar

+0

可以請你給我一個例子,以便它對其他用戶也有用嗎? –

+0

我編輯了答案,並添加了一些示例代碼 – juliocesar