Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
django内嵌表单与自定义表单_Django_Django Forms - Fatal编程技术网

django内嵌表单与自定义表单

django内嵌表单与自定义表单,django,django-forms,Django,Django Forms,嗨 我有一个在Django应用程序中使用的域模型,我想用一个表单来展示它。我已经用自定义模型表单创建了我的应用程序(没有太多更改,一些字段被排除在外等等)。模型的依赖关系如下所示: Complaint \ .--- CarInfo .--- Customer 我的视图函数如下所示: def make(request): if request.method == 'POST': parameters = copy.copy(request.POST) c

嗨 我有一个在Django应用程序中使用的域模型,我想用一个表单来展示它。我已经用自定义模型表单创建了我的应用程序(没有太多更改,一些字段被排除在外等等)。模型的依赖关系如下所示:

Complaint
   \
    .--- CarInfo
    .--- Customer
我的视图函数如下所示:

def make(request):
  if request.method == 'POST':
    parameters = copy.copy(request.POST)
    complaint = Complaint()
    carInfo = CarInfo()
    customer = Customer()

    customer_form = CustomerForm(parameters, instance=customer)
    carInfo_form = CarInfoForm(parameters, instance=carInfo)
    parameters['complaint_date'] = get_current_date()
    parameters['customer'] = 1 # dummy value to allow validation success
    parameters['car_info'] = 1 # dummy value to allow validation success
    form = ComplaintForm(parameters, instance=complaint)
    if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
      carInfo_form.save()
      customer_form.save()
      parameters['customer'] = customer.id
      parameters['car_info'] = carInfo.id
      form = ComplaintForm(parameters, instance=complaint)
      form.save()
      return index(request)
  else:
    form = ComplaintForm()
    carInfo_form = CarInfoForm()
    customer_form = CustomerForm()
  return render_to_response('complaints/make_complaint.html', {'complaint_form' : form, 'customer_form' : customer_form, 'carInfo' : carInfo_form})
complaint_info = form.cleaned_data.get('some_complaint_info')
complaint_instance = Complaint(car_info=car_instance, customer_info=customer_instance, some_complaint_info=some_complaint_info)
complaint_instance.save()
我不太喜欢这种方法,而且它并不适用于所有环境——我还没有找到它不起作用的原因。我一直在研究如何修复这段代码,并发现了类似于内联表单集(http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#inline-格式集)。这个解决方案似乎还可以,但因为我的表单是定制的,所以我可以使用它

也许有人可以给我一些建议,如何妥善解决这种情况。更清洁的解决方案非常受欢迎

已编辑
对我来说,这个解决方案根本不起作用。尽管在外键上设置了伪值,但当我调用is_valid()时,我得到了FALSE,错误消息说这些字段没有设置。我注意到django 1.2.5出现了这个问题-它发生在我打算运行这个应用程序的服务器上,但是我的笔记本电脑(也是django 1.2.5)没有这个问题。

我认为你已经有了最干净、最简单的方法,但是如果你想使用表单集,请尝试以下链接:


编辑。我想你可能会因为这个伪值(以及修改request.POST,我可以继续猜测:)而遇到问题,但是@kriegar展示了如何避免这个问题。无论如何,在一个视图中保存多个表单没有什么困难;Django表单足以支持这种情况。我的观点是,明确地这样做是最干净、最简单的方法,表单集不会对情况有太大的改善。

您可以将投诉模型的投诉日期更改为类似的内容

投诉日期=models.DateField(默认值=datetime.date.today())

这样你就可以摆脱

参数['complaint\u date']=get\u current\u date()

对于您的多表单视图,您可以使用未绑定的表单来实现所需的行为

通过将fk排除在投诉表上的车辆和客户之外,投诉表应有效。同时检查所有3个表单的.is_valid(),然后保存投诉对象所依赖的2个表单,创建投诉对象而不提交到数据库(commit=False),将客户和汽车的id添加到该对象,然后保存

在你看来

def make(request):
    if request.method == 'POST':
        customer_form = CustomerForm(request.POST)
        carInfo_form = CarInfoForm(request.POST)
        form = ComplaintForm(request.POST)

        if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
            car_instance = carInfo_form.save()
            customer_instance = customer_form.save()

            complaint_instance = form.save(commit=False)
            complaint_instance.car_info = car_instance
            complaint_instance.customer_info = customer_instance          
            complaint_instance.save()

            return index(request)
    else:
        form = ComplaintForm()
        carInfo_form = CarInfoForm()
        customer_form = CustomerForm()

    context = { 'complaint_form' : form,
                'customer_form' : customer_form, 
                'carInfo' : carInfo_form,
              }
    return render_to_response('complaints/make_complaint.html', context, context_instance=RequestContext(request))
编辑:

模型如下所示:

class CarInfo(models.Model):
    some_car_info = models.CharField()

class Customer(models.Model):
    some_customer_info = models.CharField()

class Complaint(models.Model):
    car_info = models.ForeignKey(CarInfo)
    customer_info = models.ForeignKey(Customer)
    some_complaint_info = models.CharField()
class CarInfoForm(forms.ModelForm):
    class Meta:
        model = CarInfo

class CustomerForm(forms.ModelForm):
    class Meta:
        model = Customer

class ComplaintForm(forms.ModelForm):
    class Meta:
        model = Complaint
        exclude = ('car_info', 'customer_info',) # or include = ('some_complaint_info',)
forms.py应该如下所示:

class CarInfo(models.Model):
    some_car_info = models.CharField()

class Customer(models.Model):
    some_customer_info = models.CharField()

class Complaint(models.Model):
    car_info = models.ForeignKey(CarInfo)
    customer_info = models.ForeignKey(Customer)
    some_complaint_info = models.CharField()
class CarInfoForm(forms.ModelForm):
    class Meta:
        model = CarInfo

class CustomerForm(forms.ModelForm):
    class Meta:
        model = Customer

class ComplaintForm(forms.ModelForm):
    class Meta:
        model = Complaint
        exclude = ('car_info', 'customer_info',) # or include = ('some_complaint_info',)
让我们浏览一下我在上面写的视图:

  • 第一次通过时,没有request.method,所以我们创建了3个表单

  • 这些表单将传递到模板并呈现

  • 当使用request.method==“POST”求值true再次调用视图时,我们使用request.POST中的数据创建3个绑定表单实例

    if request.method == 'POST':
        customer_form = CustomerForm(request.POST)
        carInfo_form = CarInfoForm(request.POST)
        form = ComplaintForm(request.POST)
    
  • 接下来,我们在每个表单上调用.is\u valid()方法。在我们的示例中,因为我们排除了投诉模型表单中的“customer_info”和“car_info”外键字段,所以每个表单只检查字符输入字段是否有效

  • 如果验证全部通过,那么我们可以开始将表格保存到模型中,在这里,我们需要小心填充投诉所需的fk:

        if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
            car_instance = carInfo_form.save()
            customer_instance = customer_form.save()
    
  • 使用这两个表单,我们可以像往常一样调用.save()。然而,我们将把返回值分配给car_实例和customer_实例。这些将包含我们刚刚使用表单上的.save()方法创建的CarInfo和客户模型的实例

  • 接下来,使用.save()方法中的参数,我们可以从绑定表单(包含request.POST数据)创建一个对象,而不是将其保存到数据库中

            complaint_instance = form.save(commit=False)
            complaint_instance.car_info = car_instance
            complaint_instance.customer_info = customer_instance          
            complaint_instance.save()
    
  • 为了更清楚,您还可以创建一个新的投诉对象,如下所示:

    def make(request):
      if request.method == 'POST':
        parameters = copy.copy(request.POST)
        complaint = Complaint()
        carInfo = CarInfo()
        customer = Customer()
    
        customer_form = CustomerForm(parameters, instance=customer)
        carInfo_form = CarInfoForm(parameters, instance=carInfo)
        parameters['complaint_date'] = get_current_date()
        parameters['customer'] = 1 # dummy value to allow validation success
        parameters['car_info'] = 1 # dummy value to allow validation success
        form = ComplaintForm(parameters, instance=complaint)
        if form.is_valid() and customer_form.is_valid() and carInfo_form.is_valid():
          carInfo_form.save()
          customer_form.save()
          parameters['customer'] = customer.id
          parameters['car_info'] = carInfo.id
          form = ComplaintForm(parameters, instance=complaint)
          form.save()
          return index(request)
      else:
        form = ComplaintForm()
        carInfo_form = CarInfoForm()
        customer_form = CustomerForm()
      return render_to_response('complaints/make_complaint.html', {'complaint_form' : form, 'customer_form' : customer_form, 'carInfo' : carInfo_form})
    
    complaint_info = form.cleaned_data.get('some_complaint_info')
    complaint_instance = Complaint(car_info=car_instance, customer_info=customer_instance, some_complaint_info=some_complaint_info)
    complaint_instance.save()
    
  • 渲染


也许formset工厂和内联formset可以解决您的问题。。。您可以修改或覆盖从模型创建的表单字段,对于子模型,您可以使用内联表单集

一种可能的解决办法:

在表单定义中:

class CarInfoFrm(forms.ModelForm):
    class Meta:
        model = CarInfo
        fields = (....)
carInfoForm = inlineformset_factory(Complaint, CarInfo, form=carInfoFrm,)
CustomerForm = inlineformset_factory(Complaint, Customer, form=carInfoFrm,)
在你看来:

complaint = Complaint()
carInfo = CarInfo()
customer = Customer()

cus_form = CustomerForm(parameters, instance=complaint)
car_form = CarInfoForm(parameters, instance=complaint)
comp_form = ComplaintForm(parameters, instance=complaint)

if cus_form.is_valid() and ...... :
    comp = comp_form.save(commit=False)#do not save it yet
    comp.<attr> = "some_value" #you can edit your data before save...
    comp.save()
    car = car_form(commit=False)
    # do as complaint form... edit and save... 
当您使用内联表单进行更新时,您将使用父Complaint记录对其进行初始化

car_form = CarInfoForm(parameters, instance=complaint)
所以,car_表单不接受carInfo实例,而是接受投诉实例(这是我第一次回答时的错误,所以我更正了它)。如果它创建了一个新记录,它会自动将其绑定到相关的投诉记录。如果是更新,则只更新您想要的字段


对我来说,最好使用框架的方法,而不是自己编写。通过这样做,您将保证由django进行所有验证检查。

这与我的解决方案看起来没有太大区别。如果没有carInfo和customer set的外键,表单如何进行验证?@Marcin Cylke我相信.is_valid()正在检查表单中的字段是否有效。验证表单和验证模型是两件不同的事情@Marcin,
ComplaintForm
应该可以很好地验证,因为这些字段已被
exclude
d。试试看。
DateField
的更好方法是
DateField(auto\u now\u add=True)
——“按照当前的实现,将auto\u now或auto\u now\u add设置为True将导致字段设置为editable=False和blank=True。”,确保这不是一个问题。这不是我写的更复杂的版本吗?你能总结一下你的方法的不同之处吗?我仍然担心,如果不设置fk,表单将无法验证。我将在今天晚些时候尝试此操作。请阅读我对上面的表单和模型验证的评论,似乎还有另一个问题。请张贴您的模型和表格。既然您说这完全可以,那么