簡體   English   中英

如何使用Django中基於類的通用視圖將父ID作為fk傳遞給子對象的ModelForm?

[英]How do I pass a parent id as an fk to child object's ModelForm using generic class-based views in Django?

我正在嘗試使用基於Django通用類的視圖為兩模型數據庫構建CRUD接口。 我有一個到父模型的工作CRUD接口,並且試圖讓子Create正常工作。 為了與其他Django示例保持一致,請以父級為Author,子級為Book。 允許用戶將書添加到作者的最簡單方法是什么?

用HTML術語來說,我想我要在“作者詳細信息”頁面上建立一個包含作者ID的鏈接,將該ID預先設置在Book表單中,然后讓Book表單處理將該ID用作ID。書的PK。 但是我不明白如何使用Django來實現這一目標。 我已通讀https://docs.djangoproject.com/zh-CN/1.6/topics/class-based-views/generic-editing/如何將CreateView與ModelForm一起使用如何在Django類上設置初始數據基於通用的createview和請求數據 ,並在基於類的通用視圖中將初始值設置為 modelform ,每個視圖似乎都回答了一個稍有不同的問題。

以下是相關代碼:

models.py

class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    author = models.ForeignKey(Author)
    title = models.CharField(max_length=500)

views.py

class BookCreate(CreateView):
    form_class = BookForm

    def get_success_url(self):
        return reverse('myapp:author_read',args=(self.object.author.pk))

forms.py

class BookForm(forms.Modelform):
    class Meta:
        model = Book

urls.py

url(r'^(?P<pk>\d+)/$', AuthorRead.as_view(), name='author_read'),
url(r'^book/create/(?P<author_id>\d+)/$', BookCreate.as_view(), name='book_create'),

模板/ MYAPP / author_detail.html

...
<p><a href="{% url 'myapp:book_create' author_id=Author.pk %}">Add a book</a></p>
...

模板/ MYAPP / book_form.html

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Done">
</form>

問題

1)如何從“書”頁面URL到“作者”表單中獲取作者ID,然后正確處理? 通過上面的示例代碼,Django調試器顯示出它是以這種方式存在的:

View function            Arguments      Keyword arguments         URL name
myapp.views.BookCreate   ()             {'author_id': u'1234'}    book_create

但我不明白如何從...上下文中獲取該變量? ...並放入表格中。

1a)是否可以將它設為url參數而不是URL本身的一部分,即book/create?author=1234而不是book/create/1234/ 甚至將整個內容發布為POST,以使其不屬於URL? 最佳做法是什么,如何完成?

2)一旦變量以表格形式出現,如何將其顯示為隱藏輸入,以便用戶不必查看它?

使用您在author_detail.html定義的url,即可在視圖中將author_id變量作為self.kwargs['author_id']

# views.py
class BookCreate(CreateView):
...
def form_valid(self, form):
    book = form.save(commit=False)
    author_id = form.data['author_id']
    author = get_object_or_404(Author, id=author_id)
    book.author = author
    return super(BookCreate, self).form_valid(form)
...
def get_context_data(self, **kwargs):
    context = super(BookCreate, self).get_context_data(**kwargs)
    context['a_id'] = self.kwargs['author_id']
    return context

然后在您的表單中可以添加:

class BookForm(forms.Modelform):
    ...
    def __init__(self, *args, **kwargs):
        self.fields["author_id"] = forms.CharField(widget=forms.HiddenInput())
        super(BookForm, self).__init__(self, *args, **kwargs)

然后在模板中:

  <input type=hidden name="author_id" value="{{ a_id }}">

視圖中的form_valid應該檢索ID,獲取適當的作者並將該作者設置為書籍作者。 當您設置作者時, commit=False阻止模型首先被保存,調用super將導致form.save(commit=True)被調用。

您可以將作者ID傳遞給表單,以下是一些說明:

class BookForm(forms.Modelform):
    author = None

    class Meta:
        model = Book

    def __init__(self, *args, **kwargs):
        self.author = kwargs.pop('author')
        super(BookForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        # your custom save (returns book)


class BookCreate(CreateView):
    form_class = BookForm

    def get_form_kwargs(self):
        kwargs = super(BookCreate, self).get_form_kwargs()
        kwargs['author'] = # pass your author object

        return kwargs

我有類似的情況,在執行可接受的答案步驟時,我遇到了2個錯誤(我正在使用Python 2.7)

  1. 對象沒有屬性“字段” ,該屬性通過使用對類似問題的答案得到修復: https ://stackoverflow.com/a/8928501/2097023 @scotchandsoda:

...應在調用super(...)之前放置self.fields

def __init__(self, users_list, **kw):
    super(BaseWriteForm, self).__init__(**kw)
    self.fields['recipients'].queryset = User.objects.filter(pk__in=users_list)
  1. 對象沒有屬性'get' ,該屬性已使用答案通過@luke_dupin進行了修復: https ://stackoverflow.com/a/36951830/2097023:

...此錯誤也可能是由於在用於管理模型的表單的初始化中錯誤地傳遞參數而產生的。

例:

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(self, *args, **kwargs)

注意到自我的兩次通過? 它應該是:

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM