formatting formset results values not input - django

my template looks like:
<form method="post" action="">
{{ formset.management_form }}
{% for form in formset.forms %}
{{ form.contractor }} {{ form.date }} {{ form.value }} {{ form.comment }} {{ form.operation_type }} {{ form.category }} {{ form.account }}
{% endfor %}
</form>
but the result allows to change all of fields - but i want only one.
I thought that (please notice ".value" after all but category field) solves the problem, but not.
<form method="post" action="">
{{ formset.management_form }}
{% for form in formset.forms %}
{{ form.contractor.value }} {{ form.date.value }} {{ form.value.value }} {{ form.comment.value }} {{ form.operation_type.value }} {{ form.category }} {{ form.account.value }}
{% endfor %}
</form>
UPD:
relevant view code
def detail(request, category_id):
from django.forms.models import modelformset_factory
OperationFormSet = modelformset_factory(Operation)
if request.method == "POST":
formset = OperationFormSet(request.POST, request.FILES,
queryset=Operation.objects.filter(category=category_id))
if formset.is_valid():
formset.save()
# Do something.
else:
formset = OperationFormSet(queryset=Operation.objects.filter(category=category_id))
return render_to_response("reports/operation_list.html", {
"formset": formset,
})

Your problem is that the readonly values are NOT passed back to the server, and thus your formset should fail as it's only receiving one field.
You'd want to show the value AND set a hidden field to store the data the formset is expecting. But I'd recommend a different approach...
Ultimately, a formset and form is used to display html forms and not built for anything else. You'd have to hack it to show hidden widgets, make sure users can't POST arbitrary data, etc. So instead, I would use the forms framework to only display your one editable field.
Create a ModelForm that only has one editable field
class MyModelForm(forms.ModelForm):
class Meta:
model = Operation
fields = ('category',)
MyModelFormSet = modelformset_factory(Operation, form=MyModelForm)
As for displaying values in the template, ModelForms should have their instance directly accessible via form.instance so you should be able to do something like this:
{% for form in formset %}
{{ form.instance.some_attribute }}
{{ form.category }}
{% endfor %}

Related

Every form validation in formset

Some troubles with validation.
I'm using this construction in my template:
<form method="POST">
{% csrf_token %}
{{ formset.media.js }}
{% for form in formset %}
<p>{{ form }}</p>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
And this validation in views:
def flow_type(request):
patternFormset = modelformset_factory(CashFlowPattern, fields='__all__')
if request.method == 'POST':
formset = patternFormset(request.POST)
if formset.is_valid():
formset.save()
formset = patternFormset()
template = 'cash_table/index.html'
context = {
# 'form': form,
'formset': formset
}
return render(request, template, context)
I get form at page but nothing happens after submit.
But if I use another template construction it works:
<form method="POST">
{% csrf_token %}
{{ formset.media.js }}
{{ formset }}
<button type="submit" class="btn btn-primary">Send</button>
</form>
But then I get all fields of new form at the same line.
I think you need to have {{ formset.management_form }} in the template where you iterate through the forms of the formset so that Django knows that it is a formset, and knows how many forms are in the formset, etc...
<form method="POST">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.media.js }}
{% for form in formset %}
<p>{{ form }}</p>
{% endfor %}
<button type="submit" class="btn btn-primary">Send</button>
When you use {{ formset }} the management is done automatically (it's a shortcut).
Source: https://docs.djangoproject.com/en/4.1/topics/forms/formsets/#custom-formset-validation

Unable to see error messages in registration template. Django

Good afternoon Community,
I hope you are all well.
I am building my first website and I have the following problem; when I try to create a new user, if the user enters the wrong data the template does not show the error. Any hints?
Template:
<form action= "" method='post'>
{% csrf_token %}
{% for field in form %}
<p>{{field.label}}{{field}}</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
Views.py:
def register_page(request):
form = UserForm
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('http://127.0.0.1:8000/login_user/')
context = {'form' : form}
return render(request, 'simple_investing/register.htm', context)
Forms.py:
class UserForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
As is discussed in the rendering fields manually section of the documentation, for the fields you should also render {{ field.errors }}, and the {{ form.non_field_errors }} which deals with errors not specific to one form.
The template thus should look like:
<form action= "" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
<p>
{{ field.errors }}
{{ field.label }}
{{ field }}
</p>
{% endfor %}
<button type="submit" class="btn btn-success">Create User</button>
</form>
The section also discusses how to enumerate over the errors, and apply certain styling to these errors.

Why modelformset always returns error "this field is required"?

I try to render modelformset in a template manually and when I hit submit button it gives an error saying that "This field is required.".
I create modelformset like this:
from django.forms import modelformset_factory
ImageFormset = modelformset_factory(PostImages, fields=('image',), extra=0, can_delete=True)
formset = ImageFormset(queryset=post.postimages_set.all())
And when I render modelformset like this, everything works:
{{ formset.management_form }}
{{ formset.as_p }}
But when I render it like this I get an error:
{{ formset.management_form }}
{% for f in formset %}
<img src="/media/{{ f.image.value}}" style="max-width: 400px;" alt="">
{{ f.image }}
{{ f.DELETE }}
{% endfor %}
The model formset adds a hidden field with the model instances primary key to the form to be able to identify which object is which. When you render the form manually you are not rendering it, causing the form to give you an error because it does not find it.
Simply as a best practice when rendering forms manually, just loop over a forms hidden fields and render them:
{{ formset.management_form }}
{% for f in formset %}
{% for field in f.hidden_fields %}
{{ field }}
{% endfor %}
<img src="/media/{{ f.image.value}}" style="max-width: 400px;" alt="">
{{ f.image }}
{{ f.DELETE }}
{% endfor %}

Django - Add 3 users with one form

I'm trying to create a form that save 3 users.
my forms:
class UserForm(forms.ModelForm):
class Meta:
model = MyUsers
exclude = ('address',)
my views:
def adduser(request):
if request.method == "POST":
rform = UserForm(request.POST, instance=MyUsers())
if rform.is_valid():
new_users = rform.save()
return HttpResponseRedirect...
else:
rform = UserForm(instance=MyUsers())
return render_to_response...
my template structure:
<form method="post">
{% for field in rform %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
{% for field in rform %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
{% for field in rform %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% endfor %}
<input type="submit" value="Save" />
</form>
the problem
The form works properly but add only the last inserted user.
Alasdair's suggestion (formset) is a way to generate multiple instances of the same form at once.
The forms can be rendered in the template by looping over the formset instance:
{% for form in formset %}
{{ form.id }} #PK field is MANDATORY, see reference[2] below
{{ form.field1 }}
{{ form.field2 }} #or just as something {{ form.as_p }}
{% endfor %}
In your views, formset validation is made once for all if formset.is_valid(): and rformset = formset_factory(MyUsers, extra=1, max_num=3) to create the formset.
Don't forget the imports.
References, both from Django Docs:
Formsets {1}
Creating forms from models {2}

Django Formset - Access the primary key id input

I want to render primary key id hidden input (<input type="hidden" name="form-0-id" value="5" id="id_form-0-id">) directly in my template. I know I can render whole form, but I don't want to have any labels there. Is there some way to get it using the formset? I used object initial.id, but it didn't work.
Method:
def getCellEditForm(self):
CellFormSet = modelformset_factory(Cell, extra=0, max_num=0)
form = CellFormSet(queryset=Cell.objects.filter(pk=self.id))
return form
Template:
{{ child.getCellEditForm.form.title }}
{{ child.getCellEditForm.form.parent }}
{{ child.getCellEditForm.form.initial.id }}
{% for subform in formset.forms %}
{{ subform.id }}
{% endfor %}
or
{% for subform in formset.forms %}
<input type='hidden' id='id_form{{subform.id}}' name='form{{subform.id}}' value='{{subform.id}}' />
{% endfor %}