Django ForeignKey 模型表单
Posted
技术标签:
【中文标题】Django ForeignKey 模型表单【英文标题】:Django ForeignKey Model Form 【发布时间】:2019-04-30 01:05:08 【问题描述】:我是 Django 的新手。我有两个模型,其中一个模型有外键。我在表单中使用模型表单,当我填写表单时,我的外键字段返回 null。我想要的是当我填写表单外键字段时,根据外键指出的填写。
型号:
class customerInfo(models.Model):
customerName = models.CharField(max_length = 50)
customerContent = models.TextField(max_length = 50)
createdDate= models.DateTimeField(auto_now_add = True)
def __str__(self):
return self.customerName
class productInfo(models.Model):
username = models.CharField(max_length = 50)
passwd = models.CharField(max_length = 50)
destIp = models.CharField(max_length = 50)
hostname = models.CharField(max_length = 50)
productName = models.CharField(max_length = 50)
customer = models.ForeignKey(customerInfo,on_delete = models.CASCADE,null=True)
def __str__(self):
return self.productName
表格:
class customerForm(forms.ModelForm):
class Meta:
model = customerInfo
fields = (
"customerName",
)
class addProductForm(forms.ModelForm):
class Meta:
model = productInfo
fields = (
"productName",
)
class productInfoForm(forms.ModelForm):
class Meta:
model = productInfo
fields = (
"username",
"passwd",
"destIp",
"hostname",
)
观看次数:
@login_required(login_url = "/")
def addCustomer(request):
form = customerForm(request.POST or None)
content = "form" : form,
if form.is_valid():
form.save()
customerName = form.cleaned_data['customerName']
return redirect("addproduct")
else:
return render(request,"addcustomer.html",content)
@login_required(login_url = "/")
def addProduct(request):
form = addProductForm(request.POST or None)
content = "form" : form
if form.is_valid():
global productName
productName = form.cleaned_data['productName']
return redirect("addproductinfo")
return render(request,"addproduct.html",content)
@login_required(login_url = "/")
def addProductInfo(request):
form = productInfoForm(request.POST or None)
content = "form" : form
if form.is_valid():
p = form.save(commit = False)
p.productName = productName
p.save()
return redirect("customer")
return render(request,"addproductinfo.html",content)
结果,我想在点击客户名称时看到客户的产品。不是所有的产品。 在我可以这样做之前,客户 ID 字段需要是完整的。 我希望你能理解我。
【问题讨论】:
【参考方案1】:您的问题和代码示例不清楚。 首先,您应该将模型分解为几个用例:
客户:客户列表,创建、读取、更新和删除 (CRUD) 客户 产品:产品列表,创建、读取、更新和删除 (CRUD) 产品您可以从客户列表中读取一个,然后在“显示的详细视图”中创建、更新或删除它。
您可以从产品列表中读取一个,然后在“显示的详细视图”中创建、更新或删除它。
可以通过客户列表上每行显示的额外按钮/链接来完成从客户列表到产品列表的传递,因为您的按钮/链接用于显示任何客户详细信息。
客户 PrimaryKey (PK) 通过 url 定义传递给详细信息。
path('customer/<pk>', views.customer_detail_view, name='customer_detail'),
此网址仅供展示。每个数据库操作还需要一个:创建、更新、删除。在下面为您的客户查找 urls.py 代码示例。产品也需要相同的。
from django.urls import path
from . import views
urlpatterns = urlpatterns + [
path('customer', views.customer_list_view, name='customer_list'),
path('customer/add', views.customer_add_view, name='customer_add'),
path('customer/<pk>', views.customer_detail_view, name='customer_detail'),
path('customer/<pk>/upd', views.customer_update_view, name='customer_update'),
path('customer/<pk>/del', views.customer_delete_view, name='customer_delete'),
]
请注意,create 不会通过 'pk',因为它还未知...
从列表视图调用详细视图在您的 html 模板中完成
<tbody>
% for i in customer_list %
<tr>
<td><a href="% url 'customer_detail' pk=i.id %"> i.customerName </a></td>
<td> i.customerContent|default_if_none:"" </td>
</tr>
% endfor %
</tbody>
参数由 kwargs (dict) 通过 url 传递,如果您使用 ClassBasedView (generic.DetailView),它将自动处理。如果没有,你必须像这样抓住 kwargs:kwargs.get('pk') or kwargs.pop('pk')
最后一个从 kwargs 中删除 'pk'。您也可以使用 args(无 pk 键分配)% url 'customer_detail' i.id %
传递“pk”。这也可以直接在模型的 get_absolute_url 函数中定义。
def get_absolute_url(self):
return reverse_lazy('customer_detail', args=[str(self.id)])
要么
def get_absolute_url(self):
return reverse_lazy('customer_detail', kwargs='pk': self.pk)
通过这种方式,您还可以管理您的“productName”全局变量,这是应该避免的!顺便说一句我不明白你为什么愿意将productName和productInfo的创建分开???为什么不把它们放在一起呢?
最后,如果您想为您的产品显示几个可能的编码行,您应该查看Django-FormSet。在 Google 上搜索 FormSet 教程,但这是一个更高级的功能。
具有 5 个可能的编码行的 ProductFormset 如下所示:
from django.forms import modelformset_factory
ProductFormset = modelformset_factory(
productInfo,
fields=('productName', ),
extra=5,
widgets='name': forms.TextInput(attrs=
'class': 'form-control',
'placeholder': 'Enter product Name here'
)
)
【讨论】:
【参考方案2】:如果你想重用 productInfo 模型,那么你应该使用 models.ManyToManyField 而不是 ForeignKey。正如我所理解的那样,您希望拥有一个可以让多个客户“连接”到的产品,对吧?
了解更多 --> https://docs.djangoproject.com/en/2.1/ref/models/fields/
还有更多 --> https://www.revsys.com/tidbits/tips-using-djangos-manytomanyfield/
我的用法:
class EventVocab(models.Model):
word = models.CharField(max_length = 30)
word_chinese = models.CharField(max_length = 30,blank=True, null=True)
explanation = models.TextField(max_length = 200)
example = models.TextField(max_length = 100)
word_audio = models.FileField(blank=True, null=True)
explanation_audio = models.FileField(blank=True, null=True)
example_audio = models.FileField(blank=True, null=True)
class UserVocab(models.Model):
event_vocab = models.ManyToManyField(EventVocab, related_name='event_vocab')
current_user = models.ForeignKey(User, related_name="vocab_owner", on_delete=models.CASCADE)
在此示例中,UserVocab(在您的情况下为产品)只能连接到一个用户,但一个用户可以有多个 event_vocabs(产品)
【讨论】:
不,一个客户可以有多个产品,但一个产品必须有一个客户,所以我认为我不需要 ManyToManyField。我只想在单击客户名称时查看客户的产品,但首先填写指向 customerInfo 模型中 ID 的外键字段。现在 customer(ForeignKey) 返回 null。 所以客户应该有 models.ManyToManyField(productInfo) 然后 productInfo 是客户的外键,我将更新我的答案以在我的示例中说明它以上是关于Django ForeignKey 模型表单的主要内容,如果未能解决你的问题,请参考以下文章
具有 ForeignKey 字段的模型的 Django ModelForm 无法正确显示 selectBox
Django 表单不使用 ModelChoiceField 保存 - ForeignKey
添加/更改表单中的ForeignKey字段 - Django admin