Reputation: 16002
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?
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'
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'
Upvotes: 0
Views: 925
Reputation: 234
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
Upvotes: 1