【问题标题】:Django ForeignKey Model FormDjango ForeignKey 模型表单
【发布时间】: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 字段需要是完整的。 我希望你能理解我。

【问题讨论】:

    标签: django forms modelform


    【解决方案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 是客户的外键,我将更新我的答案以在我的示例中说明它
      猜你喜欢
      • 1970-01-01
      • 2012-07-24
      • 2016-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      相关资源
      最近更新 更多