Django 外键模型表单

Django ForeignKey Model Form

我是 Django 的新手。我有两个模型,其中一个模型有外键。我在表单中使用模型表单,当我填写表单时,我的外键字段 return 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 字段需要填满。 我希望你能理解我。

如果您想重用 productInfo 模型,那么您应该 models.ManyToManyField 而不是 ForeignKey。据我正确理解,您希望拥有多个客户可以 "connect" 购买的产品,对吗?

了解更多 --> 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(产品)

您的问题和代码示例不清楚。 首先,您应该将模型分解为几个用例:

  • 客户:客户列表,创建、读取、更新和删除 (CRUD) 客户
  • 产品:产品列表,创建、读取、更新和删除 (CRUD) 产品

您可以从客户列表中读取一个,在 'detail view displayed' 上您可以创建、更新或删除它。

您可以从产品列表中阅读一个,在 'detail view displayed' 上您可以创建、更新或删除它。

从客户列表到产品列表的传递可以通过在您的客户列表上每行显示一个额外的 Button/Link 来完成,因为您的 Button/Link 用于显示任何客户详细信息。

客户主键 (PK) 通过 url 定义传递给明细。

path('customer/<pk>', views.customer_detail_view, name='customer_detail'),

此url仅供展示。每个数据库操作还需要一个:创建、更新、删除。在下面为您的客户找到 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'),
    ]

请注意,创建没有通过 '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'(无 pk 键分配){% url 'customer_detail' i.id %}。这也可以直接在模型的 get_absolute_url 函数中定义。 def get_absolute_url(自我): return reverse_lazy('customer_detail', args=[str(self.id)]) 要么 def get_absolute_url(自我): 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'
        })
    }
)