如何显示两个相关模型的表单集?
How to show formset from two related models?
有没有一种简单的方法可以显示具有两个相关模型的表单?在 models.py 文件中考虑这些:
class InvoiceList(models.Model):
invoice_number = models.IntegerField(default=0)
recipient = models.CharField(max_length=100)
class InvoiceItem(models.Model):
item_description = models.CharField(max_length=150)
list = models.ForeignKey(InvoiceList)
基本上,每张发票可以有一个或多个发票项目。
forms.py:
class InvoiceListForm(ModelForm):
class Meta:
model = InvoiceList
fields = ['invoice_number', 'recipient']
class InvoiceItemForm(ModelForm):
class Meta:
model = InvoiceItem
exclude = ('list',)
fields = ['item_description']
我的问题在views.py
def update_edit(request, invoice_id):
a = get_object_or_404(InvoiceList, pk=invoice_id)
form = InvoiceListForm(instance=a)
formset = InvoiceItemForm(instance=a)
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
file.html
<h1>Something Something Invoice</h1>
<form action="." name="stock_details" method="post">
{% csrf_token %}
{{ invoice_info.as_p }}
{% for item in items %}
{{ item.as_table }}<br>
{% endfor %}
</form>
以上内容并不完全有效。它显示 invoice_info,但不显示项目。我确定这与实例调用错误有关。有人可以帮忙吗?谢谢!
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#This view is the main page when loaded
url(r'^$', views.index, name='index'),
#This view is when viewing the details
url(r'^invoice/(?P<invoice_id>[0-9]+)/$', views.detail, name='detail'),
#This view is when doing some function
url(r'^add_new_invoice/$', views.add_new, name='add_new'),
#This view is to delete an invoice
url(r'^delete/(?P<invoice_id>[0-9]+)/$', views.delete, name='delete'),
#This view is to update an invoice
url(r'^update/(?P<invoice_id>\d+)/(?P<item_id>\d+)/$', views.update_edit, name='update_edit'),
]
index.html(这是列出发票的地方)
{% if latest_invoice_list %}
<h1>Invoices</h1><br>
<table border=1>
<tr>
<td width=50 align="center">Invoice Number</td>
<td width=200 align="center">Recipient</td>
<td align="center">Update/Resend</td>
<td align="center">Delete</td>
</tr>
{% for invoice in latest_invoice_list %}
<tr>
<td align="center">{{ invoice.invoice_number }}</td>
<td align="center"><a href="/invoice/{{ invoice.id }}/">{{ invoice.recipient }}</a></td>
<td align="center"><form action="{% url 'update_edit' invoice.id invoice.item_id %}" name="update" method="post" valign="bottom">{% csrf_token %}<input type="submit" value="Update"></form></td>
<td align="center"><form action="{% url 'delete' invoice.id %}" name="delete" method="post" valign="bottom">{% csrf_token %}<input type="submit" value="Delete"></form></td>
</tr>
{% endfor %}
</table>
<a href="{% url 'add_new' %}">Create a new invoice</a>
{% else %}
<p>No stocks were added. <a href="{% url 'add_new' %}">Create a new invoice now!</a></p>
{% endif %}
我认为你应该做 {{ items.as_table }}
而不是你做的 for
循环。
同时添加一个前缀,因为它们在同一个 HTML 表单上,这将使数据知道它属于哪个表单
更多关于前缀的信息:https://docs.djangoproject.com/en/1.9/ref/forms/api/#prefixes-for-forms
编辑
您正在尝试对 InvoiceListForm
和 InvoiceItemForm
使用 InvoiceList
模型的实例,这将不起作用。
因为你正在编辑它们,所以最好在 url 中也包含一个 item_id
,然后从
中获取 InvoiceItem
的实例
def update_edit(request, invoice_id, item_id):
a = get_object_or_404(InvoiceList, pk=invoice_id)
i = get_object_or_404(InvoiceItem, pk=item_id)
form = InvoiceListForm(instance=a, prefix="list")
formset = InvoiceItemForm(instance=i, prefix="item")
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
或 只需包含 item_id
,然后从外键中获取 InvoiceList
实例。
def update_edit(request, item_id):
i = get_object_or_404(InvoiceItem, pk=item_id)
form = InvoiceListForm(instance=i.list, prefix="list")
formset = InvoiceItemForm(instance=i, prefix="item")
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
好的,所以我设法通过使用 inlineformset_factory 解决了它,但放在 forms.py 文件中。所以在这里以防万一有人在寻找它:
forms.py
# Added this new line at the top
from django.forms.models import inlineformset_factory
# Placed this at the very bottom
InvoiceFormSet = inlineformset_factory(InvoiceList, InvoiceItem, fields=('item_description',), extra=0)
views.py
# Added this line at the top
from .forms import InvoiceFormSet
# Adjusted the def to this
def update_edit(request, invoice_id):
# Confirm and acquire the stuff from the main model
a = get_object_or_404(InvoiceList, pk=invoice_id)
# Acquire the related model stuff under the main model & assign to "b"
b = InvoiceFormSet(instance=a, prefix="item")
# Acquire the stuff from the main model & assign to "form"
form = InvoiceListForm(instance=a, prefix="list")
return render(request, 'file.html', {'invoice_info': form, 'items': b})
file.html
<h1>Something Something Invoice</h1>
<form action="." name="stock_details" method="post">
{% csrf_token %}
{{ invoice_info.as_p }}
{% for item in items %}
{{ item.as_table }}<br>
{% endfor %}
</form>
"item in items" 现在也可以使用,可以通过这种方式遍历内容。奇怪的是,有一个 "Delete" 复选框单独出现。
有没有一种简单的方法可以显示具有两个相关模型的表单?在 models.py 文件中考虑这些:
class InvoiceList(models.Model):
invoice_number = models.IntegerField(default=0)
recipient = models.CharField(max_length=100)
class InvoiceItem(models.Model):
item_description = models.CharField(max_length=150)
list = models.ForeignKey(InvoiceList)
基本上,每张发票可以有一个或多个发票项目。
forms.py:
class InvoiceListForm(ModelForm):
class Meta:
model = InvoiceList
fields = ['invoice_number', 'recipient']
class InvoiceItemForm(ModelForm):
class Meta:
model = InvoiceItem
exclude = ('list',)
fields = ['item_description']
我的问题在views.py
def update_edit(request, invoice_id):
a = get_object_or_404(InvoiceList, pk=invoice_id)
form = InvoiceListForm(instance=a)
formset = InvoiceItemForm(instance=a)
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
file.html
<h1>Something Something Invoice</h1>
<form action="." name="stock_details" method="post">
{% csrf_token %}
{{ invoice_info.as_p }}
{% for item in items %}
{{ item.as_table }}<br>
{% endfor %}
</form>
以上内容并不完全有效。它显示 invoice_info,但不显示项目。我确定这与实例调用错误有关。有人可以帮忙吗?谢谢!
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
#This view is the main page when loaded
url(r'^$', views.index, name='index'),
#This view is when viewing the details
url(r'^invoice/(?P<invoice_id>[0-9]+)/$', views.detail, name='detail'),
#This view is when doing some function
url(r'^add_new_invoice/$', views.add_new, name='add_new'),
#This view is to delete an invoice
url(r'^delete/(?P<invoice_id>[0-9]+)/$', views.delete, name='delete'),
#This view is to update an invoice
url(r'^update/(?P<invoice_id>\d+)/(?P<item_id>\d+)/$', views.update_edit, name='update_edit'),
]
index.html(这是列出发票的地方)
{% if latest_invoice_list %}
<h1>Invoices</h1><br>
<table border=1>
<tr>
<td width=50 align="center">Invoice Number</td>
<td width=200 align="center">Recipient</td>
<td align="center">Update/Resend</td>
<td align="center">Delete</td>
</tr>
{% for invoice in latest_invoice_list %}
<tr>
<td align="center">{{ invoice.invoice_number }}</td>
<td align="center"><a href="/invoice/{{ invoice.id }}/">{{ invoice.recipient }}</a></td>
<td align="center"><form action="{% url 'update_edit' invoice.id invoice.item_id %}" name="update" method="post" valign="bottom">{% csrf_token %}<input type="submit" value="Update"></form></td>
<td align="center"><form action="{% url 'delete' invoice.id %}" name="delete" method="post" valign="bottom">{% csrf_token %}<input type="submit" value="Delete"></form></td>
</tr>
{% endfor %}
</table>
<a href="{% url 'add_new' %}">Create a new invoice</a>
{% else %}
<p>No stocks were added. <a href="{% url 'add_new' %}">Create a new invoice now!</a></p>
{% endif %}
我认为你应该做 {{ items.as_table }}
而不是你做的 for
循环。
同时添加一个前缀,因为它们在同一个 HTML 表单上,这将使数据知道它属于哪个表单
更多关于前缀的信息:https://docs.djangoproject.com/en/1.9/ref/forms/api/#prefixes-for-forms
编辑
您正在尝试对 InvoiceListForm
和 InvoiceItemForm
使用 InvoiceList
模型的实例,这将不起作用。
因为你正在编辑它们,所以最好在 url 中也包含一个 item_id
,然后从
InvoiceItem
的实例
def update_edit(request, invoice_id, item_id):
a = get_object_or_404(InvoiceList, pk=invoice_id)
i = get_object_or_404(InvoiceItem, pk=item_id)
form = InvoiceListForm(instance=a, prefix="list")
formset = InvoiceItemForm(instance=i, prefix="item")
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
或 只需包含 item_id
,然后从外键中获取 InvoiceList
实例。
def update_edit(request, item_id):
i = get_object_or_404(InvoiceItem, pk=item_id)
form = InvoiceListForm(instance=i.list, prefix="list")
formset = InvoiceItemForm(instance=i, prefix="item")
return render(request, 'file.html', {'invoice_info': form, 'items': formset})
好的,所以我设法通过使用 inlineformset_factory 解决了它,但放在 forms.py 文件中。所以在这里以防万一有人在寻找它:
forms.py
# Added this new line at the top
from django.forms.models import inlineformset_factory
# Placed this at the very bottom
InvoiceFormSet = inlineformset_factory(InvoiceList, InvoiceItem, fields=('item_description',), extra=0)
views.py
# Added this line at the top
from .forms import InvoiceFormSet
# Adjusted the def to this
def update_edit(request, invoice_id):
# Confirm and acquire the stuff from the main model
a = get_object_or_404(InvoiceList, pk=invoice_id)
# Acquire the related model stuff under the main model & assign to "b"
b = InvoiceFormSet(instance=a, prefix="item")
# Acquire the stuff from the main model & assign to "form"
form = InvoiceListForm(instance=a, prefix="list")
return render(request, 'file.html', {'invoice_info': form, 'items': b})
file.html
<h1>Something Something Invoice</h1>
<form action="." name="stock_details" method="post">
{% csrf_token %}
{{ invoice_info.as_p }}
{% for item in items %}
{{ item.as_table }}<br>
{% endfor %}
</form>
"item in items" 现在也可以使用,可以通过这种方式遍历内容。奇怪的是,有一个 "Delete" 复选框单独出现。