简体   繁体   中英

Django how to add an initial value with modelformset_factory?

How can I pass an initial value to Product_Form when using it with modelformset_factory ?

This is my attempt:

models.py:

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=45)
    qty = models.IntegerField()
    price = models.IntegerField()

forms.py:

from django import forms
from .models import Product

class ProductForm(forms.BaseModelFormSet):
    def __init__(self, *args, **kwargs):
    super(Product_Form, self).__init__(*args, **kwargs)

    qty = kwargs.get('qty','')
    print(qty) #prints blank string
    self.queryset = Product.objects.filter(qty=qty)
    class Meta:
        model = Product
        fields = ['name', 'qty', 'price']

views.py:

from django.shortcuts import render
from django.views import View
from django.forms import modelformset_factory
from .forms import Product_Form
from .models import Product

class Inventory(View):
    def __init__(self):
        pass

    def get(self, req):

        product_form = modelformset_factory(Product, fields=('qty','price','name'), 
                       formset=Product_Form) 

        form = product_form(initial=[
             {'qty':0},
        ])
        context = {
            'form':form,
        }
        return render(req, 'base.html', context)

the data I need to pass to it is the result of a Search_Form , (IE user input) which is used to filter the Products query.

When I try to render base.py , I get the following error:

invalid literal for int() with base 10: ''

Which appears to be due to the fact that an empty string is being inserted into Product.objects.filter(qty='')

I am taking most of this code directly from the docs , so I'm really not sure why it isn't working.

What am I missing here?

update

Changing this:

form = product_form(initial=[
     {'qty':0},
])

To this:

form = product_form(qty=0)

yields an error:

init () got an unexpected keyword argument 'qty'

update 2

I modified my code based on bdoubleu's answer, and I get the following error:

Template error:
In template /Users/jane/Code/mu_env/mu/inventory/templates/partials/product_form.html, error at line 2
   __init__() got an unexpected keyword argument 'use_required_attribute'
   1 : <form action="/inventory/update" method="POST" id="search_form"> {% csrf_token %}
   2 :  {{ product_form }} 
   3 : <button>save</button>
   4 : </form>
   5 : 

Traceback:

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/views/generic/base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "/Users/jane/Code/mu_env/mu/inventory/views.py" in get
  31.         return render(req, 'inventory/base.html', context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/shortcuts.py" in render
  36.     content = loader.render_to_string(template_name, context, request, using=using)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/loader.py" in render_to_string
  62.     return template.render(context, request)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/backends/django.py" in render
  61.             return self.template.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  171.                     return self._render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/defaulttags.py" in render
  309.                 return nodelist.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/loader_tags.py" in render
  188.             return template.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  173.                 return self._render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render
  993.         return render_value_in_context(output, context)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/template/base.py" in render_value_in_context
  972.             value = str(value)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/utils/html.py" in <lambda>
  388.     klass.__str__ = lambda self: mark_safe(klass_str(self))

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in __str__
  64.         return self.as_table()

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in as_table
  404.         forms = ' '.join(form.as_table() for form in self)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in __iter__
  68.         return iter(self.forms)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/utils/functional.py" in __get__
  80.         res = instance.__dict__[self.name] = self.func(instance)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in forms
  136.                  for i in range(self.total_form_count())]

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in <listcomp>
  136.                  for i in range(self.total_form_count())]

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/models.py" in _construct_form
  620.         form = super()._construct_form(i, **kwargs)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/formsets.py" in _construct_form
  172.         form = self.form(**defaults)

File "/Users/jane/Code/mu_env/mu/inventory/forms.py" in __init__
  31.         super(Product_Form, self).__init__(*args, **kwargs)

File "/Users/jane/Code/mu_env/env/lib/python3.7/site-packages/django/forms/models.py" in __init__
  569.         super().__init__(**{'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix, **kwargs})

Exception Type: TypeError at /inventory/search
Exception Value: __init__() got an unexpected keyword argument 'use_required_attribute'

The initial keyword argument is for passing initial data to a form, to pass form kwargs to a formset you'll need to use form_kwargs .

form = product_form(form_kwargs={'qty': 0})

It's worth noting for what you're trying to accomplish it's not necessary to pass any extra kwargs to the formset because you can modify the queryset directly .

To do this the ProductForm should be a django Form , not a BaseModelFormset .

forms.py

from django import forms
from .models import Product

class ProductForm(forms.Form):

    class Meta:
        model = Product
        fields = ['name', 'qty', 'price']

ProductFormSet = forms.modelformset_factory(Product, form=ProductForm)

So putting it together in your current view:

from .forms import ProductFormSet

class Inventory(View):
    def get(self, request, *args, **kwargs):
        qty = self.request.GET.get('qty', None)
        qs = Product.objects.all()
        if qty:
            qs = qs.filter(qty=qty)

        form = ProductFormSet(queryset=qs)

        context = {
            'form':form,
        }
        return render(req, 'base.html', context)

Here's an alternate version using FormView :

from django.views.generic import FormView

from .forms import ProductFormSet

class Inventory(FormView):
    form_class = ProductFormSet

    def get_form_kwargs(self)
        kwargs = super().get_form_kwargs()
        qty = self.request.GET.get('qty', None)
        qs = Product.objects.all()
        if qty:
            qs = qs.filter(qty=qty)
        kwargs['queryset'] = qs
        return kwargs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM