I keep getting the error:
[u'ManagementForm data is missing or has been tampered with']
I can't figure out why either. Here is my view:
def CreateWorkout(request):
WorkoutInlineFormSet = inlineformset_factory(workout,exercise)
if request.method == "POST" :
formset = WorkoutInlineFormSet(request.POST)
if formset.is_valid():
formset.save();
else:
formset = WorkoutInlineFormSet()
return render_to_response('submit.html',{'formset': formset},context_instance=RequestContext(request))
And here is my template:
<body>
<form method="POST" action ="">
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
</form>
</body>
I've read that you have to include the formset.management_form, and I have. I thought that would be an easy fix, but I haven't been able to figure out the problem.
I have meet this problem.
The reason is there is NO something like form-TOTAL_FORMS, form-INITIAL_FORMS and form-MAX_NUM_FORMS) in your POST data.
You should use {{ formset.as_p }}, this will render the management_form data from the formset. If you want to make the custom formset rendering, you should not forget the management_form of the formset to let POST data be with the mangement_form data.
When you use inline formset, you need to provide the instance that the objects relate to.
# First, fetch the instance from the db
workout = code_that_fetches_instance()
if request.method == "POST" :
formset = WorkoutInlineFormSet(request.POST, instance=workout)
...
else:
formset = WorkoutInlineFormSet(instance=workout)
See the example in the docs on using an inline formset in a view for more information.
If workout and exercise are your models, you should follow the python convention and rename them Workout and Exercise. Lowercase workout should be the instance that all the exercises in your formset are linked to.
Change this:
formset = WorkoutInlineFormSet(request.POST)
to this:
formset = WorkoutInlineFormSet(request.POST or None, request.FILES or None)
Related
Sure I've missed something obvious, but any help appreciated.
I have a form model:
class UserForm(forms.Form):
name = forms.CharField()
A view:
def userform(req):
context = {}
context['user_form'] = UserForm()
context['message'] = 'test message'
return render(req, 'apps/userform.html', context)
And a template:
{% extends 'base.html' %}
{% block title %} | User Form {% endblock %}
{% block content %}
<h1>Form page</h1>
<form method='POST'>
{% csrf_token %}
{{ user_form }}
<button type='submit'>Send</button>
</form>
{{ message }}
{% endblock %}
I'm pretty sure everything is connected correctly and imported as required - the 'message' property on context renders fine under the form.
However, {{ user_form }} in the template renders the actual Form object instance, rather than the actual form field I'm expecting. I see:
<userform.views.UserForm object at 0x7fcab17e5c10>
Then the form submit button.
What have I missed?
Django 4, if that matters.
So the issue was I had a class based view in the views file with the same name as my Form class - I guess that was getting instantiated, rather than the Form class. Commented out the CBV and everything worked.
If I'd looked harder at the error message, I would have probably seen this sooner as the instantiated object is clearly in the views folder, rather than the forms one...
I got crispy forms working with my model, though the form looks plain and bootstrap not showing up, also there seems to be no button. Even when adding button and clicking it(it refreshes) no data has been saved to the database. I have tried many ways. What seems to be wrong? Any help would be highly appreciated.
forms.py
class PlotForm(forms.ModelForm):
helper = FormHelper()
helper.form_tag = False
helper.form_method = 'POST'
class Meta:
model = Plot
fields = '__all__'
views:
def plot_form(request):
return render(request, 'plot_form.html', {'form': PlotForm()})
the html:
{% load crispy_forms_tags %}
<form action="" method="POST">
{% crispy form %}
<input type="submit" class="btn btn-default" value="save">
First the {% csrf_token %} is missing. Second If I remember it correct you need to use {{ form|crispy }} to load the form.
And third I would recommend to use Widget Tweaks
<form method='POST' action="/" enctype='multipart/form-data'>
{% load widget_tweaks %}
{% csrf_token %}
{{ form.first_name |add_class:"customCSS1 customCSS2" }}
{{ form.second_name |add_class:"customCSS3 customCSS4" }}
</form>
{{ form.media.js }}
with this plugin you can style the form as you wish. All Css classes work. Crispy is nice but you have get into the documentation and there are always some workarounds you need to do when you want to style the form. With Widget Tweaks you can simply apply any CSS class. When you really know your way around with crispy you can do a lot but to get to that point....
I switched at some Point and now everything works like a charm
Hope that helps if not leave a comment :)
Edit
I just saw something in your views.py. You are not referencing the form correct as far as I can tell.
from appName.forms import PlotForm
def plot_form(request):
form = PlotForm(request.POST or None, request.FILES or None) #request files is only required when you want to upload a file
if form.is_valid():
instance = form.save(commit = False)
...
instance.save()
#messages.success(request, 'form was saved') #optional
context = {
'form':form,
}
return render(request, 'AppName/plot_form.html', context)
Maybe that will do the trick. You did not have a form validation and Im not sure if the "()" at {'form': PlotForm()} would break the code.
I also faced the same issue. Solved it by testing it on firefox instead of google chrome. Apparently, Chrome does not load CSS style for a few local web apps. Got it to work after following this hack. https://css-tricks.com/new-in-chrome-css-overview/
So, a total Django Model Formset Newb question. I'm trying to save my form and keep getting this error:
['ManagementForm data is missing or has been tampered with']
Here is what I have for my TemplateView:
class AttendanceTemplate(TemplateView):
template_name = 'attendance/index.html'
def get_context_data(self, **kwargs):
context = super(AttendanceTemplate, self).get_context_data(**kwargs)
instruction = Instruction(self.request.user.username)
sections_list = self.request.GET.getlist('sections_list')
term = self.request.GET.get('term', instruction.term)
enrollments = Enrollment.objects.using('wisp').prefetch_related('profile').filter(section_id__in=['111111'], term=term)
attendanceQuery = Enrollment.objects.using('wisp').prefetch_related('student').filter(section_id__in=['111111'], term=term)
for enrollment in attendanceQuery:
attendance, created = Attendance.objects.update_or_create(
section_id=enrollment.section_id,
term=enrollment.term,
first_name=enrollment.student.first_name,
last_name=enrollment.student.last_name,
email_address=enrollment.student.email_address,
)
something = Attendance.objects.filter(section_id__in=['111111'], term=term)
formset = AttendanceFormSet(queryset=something)
combined = zip(enrollments, formset)
context['combined'] = combined
return context
Here is how I'm trying to save the form:
def post(self, request):
formset = AttendanceFormSet(request.POST)
if formset.is_valid():
for thing in formset:
formset = thing.save()
return render_to_response("template/index.html",{'formset': formset}, RequestContext(request))
else:
return HttpResponse(error.msg)
Here is what I have in my template:
<form method="POST" action="">
{% csrf_token %}
{% for enrollment, form in combined %}
<div class="wrapper-formset">
<div>
{{ form.first_name.value }}
{{ form.last_name.value }}
{{ form.email_address.value }}
</div>
<div class="clear-all"></div>
</div>
{% endfor %}
<button type="submit" class="save btn btn-default">Save</button>
</form>
Am I saving my form wrong? Maybe my loop is wrong? Also, I'd prefer to print each field out individually, so using the "myform.management_Form" may not work for me? (e.g., myform.management_form.field_name)
If you render the forms separately, then you must include the management form in your template. The fact that you are zipping your forms makes no difference.
Including the management form is easy, just add {% formset.management_form %} to your template.
<form method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for enrollment, form in combined %}
...
For that to work, you'll need to make sure that formset is in the template context, for example:
context['formset'] = formset
You might find the docs on using model formsets in the template useful. It would be a good idea to start with the simplest option, {{ formset }}, test it, then gradually customize the template. That makes it easier to debug when stuff goes wrong. At the moment it looks like you have missed out {{ form.id }}.
I'm familar with using templates to collect the data, but on displaying is there a smart way that Django will display the fields and populate them with the right values. I can do it manually of course, but the model knows the field type. I didn't see any documentation on this. For example I collect data from the template with:
<strong>Company Name</strong>
<font color="red">{{ form.companyname.errors }}</font>
{{ form.companyname }}
where form is my company model containing all the fields. How would I go about ensuring that I could use this type of methodology such that Django would render the text fields and populate with the current values. For example is there a way to send in values in the following way:
myid = int(self.request.get('id'))
myrecord = Company.get_by_id(myid)
category_list = CompanyCategory.all()
path = os.path.join(os.path.dirname(__file__), 'editcompany.html')
self.response.out.write(template.render(path, {'form': myrecord, 'category_list': category_list}))
Can I do the same this with records and will the template populate with values sent in? Thanks
It sounds like you may be confused about the difference and proper usage of Form vs ModelForm
Regardless of which type of form you use, the templating side of forms stays the same:
Note: all of the values in your form (as long as its bound to POST or has an instance) will be prepopulated at render.
<form class="well" action="{% url member-profile %}" method="POST" enctype="multipart/form-data">{% csrf_token %}
<fieldset>
{{ form.non_field_errors }}
{{ form.display_name.label_tag }}
<span class="help-block">{{ form.display_name.help_text }}</span>
{{ form.display_name }}
<span class="error">{{ form.display_name.errors }}</span>
{{ form.biography.label_tag }}
<span class="help-block">{{ form.biography.help_text }}</span>
{{ form.biography }}
<span class="error">{{ form.biography.errors }}</span>
<input type="submit" class="button primary" value="Save" />
</fieldset>
</form>
if you want to be populating a form from a record (or submit a form as a record) its probably best to use ModelForm
EX a profile form that doesn't display the User FK dropdown:
class ProfileForm(forms.ModelForm):
"""Profile form"""
class Meta:
model = Profile
exclude = ('user',)
The View:
def profile(request):
"""Manage Account"""
if request.user.is_anonymous() :
# user isn't logged in
messages.info(request, _(u'You are not logged in!'))
return redirect('member-login')
# get the currently logged in user's profile
profile = request.user.profile
# check to see if this request is a post
if request.method == "POST":
# Bind the post to the form w/ profile as initial
form = ProfileForm(request.POST, instance=profile)
if form.is_valid() :
# if the form is valid
form.save()
messages.success(request, _(u'Success! You have updated your profile.'))
else :
# if the form is invalid
messages.error(request, _(u'Error! Correct all errors in the form below and resubmit.'))
else:
# set the initial form values to the current user's profile's values
form = ProfileForm(instance=profile)
return render(
request,
'membership/manage/profile.html',
{
'form': form,
}
)
notice that the outer else initializes the form with an instance: form = ProfileForm(instance=profile) and that the form submit initializes the form with post, BUT still binds to instance form = ProfileForm(request.POST, instance=profile)
If you're looking at forms, it would seem like a good idea to start with Django's forms framework, specifically forms for models.
I'm having some problems with model formsets in django.
# forms.py
OppFormSet = modelformset_factory(Opportunity, fields=opp_fields)
# views.py
def index2(request):
queryset = Opportunity.objects.for_user(request.user).filter(is_deleted=False)
if request.method == 'POST':
formset = OppFormSet(request.POST, queryset=queryset)
else:
formset = OppFormSet(queryset=queryset)
return render_to_response("opp_index2.tmpl", { "formset" : formset}, context_instance=RequestContext(request))
Here are my 2 questions regarding model forms:
In my template I have {% for form in formset %} to create the forms in a table, but somehow, I keep getting an extra blank row, as if there is an additional blank form in the formset.
If i use {{ form.instance.id }} to output an id while iterating through the formset, it prints out ok. However, if I do a {% url summary form.instance.id %} I keep getting an error regarding no NoReverseMatch with arguments (None,). It seems like when using form.instance.id in a template tag, it doesn't work. Is that true? If so, how do i circumvent it?
Thank you in advance.
Use {% for form in formset.forms %} This "blank form" is ManagementForm