MultiValueDictKeyError when submitting ModelFormSet - python

When trying to submit my ModelFormSet I am getting a MultiValueDictKeyError. The error message is not very descriptive so I'm not sure why the error is being thrown.
Here is the view:
def admin_tools(request):
ElectionFormSet = modelformset_factory(Election, exclude=('Complete',), formset=BaseElectionFormSet, extra=0)
if request.method == 'POST':
if 'new_election' in request.POST:
new_election = NewElectionForm(request.POST)
if new_election.is_valid():
election = new_election.save(commit=False)
election.save()
messages.add_message(request, messages.SUCCESS, 'Election created')
return redirect(reverse('elections:home'))
elif 'edit_elections' in request.POST:
formset = ElectionFormSet(request.POST)
if formset.is_valid():
formset.save()
messages.add_message(request, messages.SUCCESS, 'Election settings saved')
return redirect(reverse('elections:home'))
else:
new_election_form = NewElectionForm()
formset = ElectionFormSet()
return render(request, 'admin/admin_tools.html',{
'new_election': new_election_form,
'formset': formset,
})
Here is the relevant section of the template:
<div class="card-body">
<h4>Toggle election settings:</h4>
<form method="post" action="">
{{ formset.management_form }}
{% for form in formset %}
{% csrf_token %}
<div class='card'>
<div class='card-body w-75 mx-auto'>
<div class='row'>
<div class='col-6 text-center'>
<p>Name<br>{{form.Name}}</p>
</div>
<div class='col-6 text-center'>
<p>Videos<br>{{form.FlipGrid}}</p>
</div>
</div>
<div class='row'>
<div class='col-12 text-center'>
<p>Description<br>{{form.Description}}</p>
</div>
</div>
<div class='row'>
<div class='col-6 text-center'>
<p>Allow registration: {{form.CandidateReg}}</p>
</div>
<div class='col-6 text-center'>
<p>Allow voting: {{form.VotingOpen}}</p>
</div>
</div>
</div>
</div>
{% endfor %}
<div class='text-center'>
<br><button type="submit" class='btn btn-outline-dark' name='edit_elections'>Save</button>
</div>
</form>
</div>
The error is raise MultiValueDictKeyError(repr(key))
django.utils.datastructures.MultiValueDictKeyError: "'form-0-id'"
and it was flagged on the line: if formset.is_valid(): of the view.
How do I resolve this error and get the formset to correctly submit and update the data in the model?

Related

Redirecting my Login page to a new page and if user is remembered and already logged in show this new page

Setting.py
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
LOGIN_REDIRECT_URL = '/home1'
LOGIN_URL = 'login'
views.py
def home(request):
return render(request, 'users/home.html')
class RegisterView(View):
form_class = RegisterForm
initial = {'key': 'value'}
template_name = 'users/register.html'
def dispatch(self, request, *args, **kwargs):
# Redireccion a Home si ya esta logged
if request.user.is_authenticated:
return redirect(to='/users/home1')
return super(RegisterView, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect(to='login')
return render(request, self.template_name, {'form': form})
class CustomLoginView(LoginView):
form_class = LoginForm
def form_valid(self, form):
remember_me = form.cleaned_data.get('remember_me')
if not remember_me:
# Expira 0seg
self.request.session.set_expiry(0)
# Cookies
self.request.session.modified = True
# Hasta que los cookies expriran
return super(CustomLoginView, self).form_valid(form)
urls.py
urlpatterns = [
re_path('admin/', admin.site.urls),
re_path('', include('users.urls')),
re_path('login/', CustomLoginView.as_view(redirect_authenticated_user=True, template_name='users/login.html',
authentication_form=LoginForm), name='login'),
re_path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
re_path('password-reset/', ResetPasswordView.as_view(), name='password_reset'),
re_path('password-reset-confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'),
name='password_reset_confirm'),
re_path('password-reset-complete/',
auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'),
name='password_reset_complete'),
path('password-change/', ChangePasswordView.as_view(), name='password_change'),
re_path(r'^oauth/', include('social_django.urls', namespace='social')),
re_path('home1/', auth_views.LoginView.as_view(redirect_authenticated_user=True, template_name='users/home1.html'), name='home1'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Login.html
extends "users/base.html" %}
{% block title %} Login Page {% endblock title%}
{% block content %}
<div class="form-content my-3 p-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="card-header justify-content-center">
<h3 class="font-weight-light my-1 text-center">Iniciar Sesion</h3>
</div>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<a href="{% url 'social:begin' 'github' %}"
class="btn btn-link btn-lg active btn-block">Iniciar sesion con GitHub</a>
<a href="{% url 'social:begin' 'google-oauth2' %}"
class="btn btn-link btn-lg active btn-block">Iniciar sesion con Google</a>
<hr>
<p class="text-center"><strong>OR</strong></p>
<hr>
<label class="small mb-1">Usuario</label>
{{ form.username }}
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1">Contrasena
</label>
{{ form.password }}
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<!-- Add a Remember me functionality -->
{{ form.remember_me }}
<label> Recuerdame</label>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group mt-0 mb-1">
<button name="login" class="col-md-12 btn btn-dark" id="login">Sign in</button>
</div>
</div>
</div>
</form>
</div>
<div class="card-footer text-center">
<div class="small">
No tiene cuenta? Cree una! <br>
<i>Olvido su contrasena?</i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
My templates
Got 12 templates, home, home1, base, login, logout, register, profile, password reset, etc
I continue to get a too many redirects error, or when I try and change the redirection with a get and post method it says the template doesn't exist

HTML form ignores file section

When I submit my form, by analyzing request I saw that every field is submitted except file data and I don't know why. I would really be happy if anybody could give me a hint how to solve this problem.
my route.py file
#users.route("/account", methods=["GET", "POST"])
#login_required
def account():
form = UpdateAccountForm()
if form.validate_on_submit():
if form.pic.data:
file_data = save_pict(form.pic.data)
current_user.picture = file_data
else:
print("no data was sent")
current_user.username = form.username.data
current_user.email = form.email.data
db.session.commit()
flash("Your profile was updated!", "success")
return redirect(url_for("users.account"))
forms file
class UpdateAccountForm(FlaskForm):
username = StringField("Username", validators=[DataRequired(), Length(min=5, max=15)])
email = StringField("Email", validators=[DataRequired(), Email()])
pic = FileField("Update Picture", validators=[FileAllowed(["jpeg", "png"])])
submit = SubmitField("Update")
HTML file
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src={{image}}>
<br>
<div class="media-body">
<br>
<h2 class="account-heading">{{current_user.username}}</h2>
<p class="secondary">{{current_user.email}}</p>
</div>
</div>
<div class="registration-form">
<form method="post" action="" enctype="multipart/form-data">
{{form.hidden_tag()}}
<fieldset class="form-group"><br>
<legend class="border-bottom mb-4">Account info</legend>
<div class="form-group">
{{form.username.label(class="form-control-label")}}
{%if form.username.errors%}
{{form.username(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{%for error in form.username.errors%}
<span>{{error}}</span>
{%endfor%}
</div>
{%else%}
{{form.username(class="form-control form-control-lg")}}
{%endif%}
</div>
<div class="form-group">
{{form.email.label(class="form-control-label")}}
{%if form.email.errors%}
{{form.email(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{%for error in form.email.errors%}
<span>{{error}}</span>
{%endfor%}
</div>
{%else%}
{{form.email(class="form-control form-control-lg")}}
{%endif%}
</div>
<div class="form-group">
{{ form.pic.label() }}
{{ form.pic(class="form-control-file") }}
{% if form.pic.errors %}
{% for error in form.pic.errors %}
<span class="text-danger">{{ error }}</span></br>
{% endfor %}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{form.submit(class="btn btn-outline-info")}}
</div>
</form>
</div>
</div>
So when I inspect body of the request every field is present except file field, and nothing is submitted to database
request body photo

Receiving an Error when a Form is submitted related to cleaned_data

I am trying to submit a Message form for my Django Project but I keep receiving an error:
AttributeError at /
'MessageForm' object has no attribute 'cleaned_data'
I am not sure what is the reason for getting this error although I revised the https://docs.djangoproject.com/en/3.1/topics/forms/
Here is my views.py
def home(request):
if request.method == 'POST': #Check Post
form = MessageForm(request.POST)
if form.is_valid():
data = MessageForm() #Create Relationship with Model
data.name= form.cleaned_data['name']
data.email= form.cleaned_data['email']
data.message= form.cleaned_data['message']
data.ip = request.META.get('REMOTE_ADDR')
data.save()
messages.success(request,'Your Message has been sent, Thank you!')
return HttpResponseRedirect('base:home')
template_name = 'base/home.html'
form = MessageForm()
----------------------other unrelated contexts--------------------
context = {
'form': form,
}
return render(request, template_name, context)
Here is the urls.py
urlpatterns = [
path('', views.home,name='home')
]
Here is the template.html
<form class="form" id="form" method="post">
{% csrf_token %}
<div class="row">
<div class="col-md-6">
<div class="form-group">
<input name="name" id="form-name" type="text" placeholder="Your Name" class="form-control input" autocomplete="off"/>
<div id="name-error"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<input name="email" id="form-email" type="email" class="form-control input" placeholder="Your E-Mail" autocomplete="off">
<div id="email-error"></div>
</div>
</div>
</div>
<div class="form-group">
<textarea name="message" id="form-message" class="form-control input" rows="7" placeholder="Your Message here ..." autocomplete="off"></textarea>
<div id="message-error"></div>
</div>
<!-- Messages -->
{% if messages %}
{% for message in messages %}
<div class="container">
<div class=" alert alert-{{ message.tags }}">
{{ message }}
</div>
</div>
{% endfor %}
{% endif %}
<!-- Messages -->
<input id="form-submit" type="submit">
<div class="send-message" >
Send <i class="ni ni-send"></i>
</div>
</form>
You are constructing a new form, but that does not make much sense. Once your orignal form is validated, you can save that form, so:
def home(request):
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
form.instance.ip = request.META.get('REMOTE_ADDR')
form.save()
messages.success(request,'Your Message has been sent, Thank you!')
return redirect('base:home')
# …

Django 2 form in modal

Im tries to open in Django the user edit form in Bootstrap modal. But the form is empty, only the save button is shown. But I don't understand how I can make the connection. If I call the edit page directly, then I can edit the user
127.0.0.1:8000/account/edit/
index.html, includes the referral to the form
{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="panel panel-default">
<div class="panel-body">
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form action="{% url 'account:edit_profile' %}">
<input type="submit" value="Edit" />
</form>
<form action="{% url 'account:change_password' %}">
<input type="submit" value="Change Login" />
</form>
<br>
Open Modal
<br>
<div class="control-label col-sm-2">
First name:
</div>
<div class="col-sm-2">
{{ user.first_name }}
</div><br>
<div class="control-label col-sm-2">
Last name:
</div>
<div class="col-sm-2">
{{ user.last_name }}
</div><br>
<div class="control-label col-sm-2">
Email:
</div>
<div class="col-sm-2">
{{ user.email }}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="edit-profile-modal" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header" align="center">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</div>
<div id="div-forms">
{% include "account/edit_profile.html" with form=form %}
</div>
</div>
</div>
</div>
{% endblock %}
edit_profile.html
{% block head %}
{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<h3>Profile</h3>
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
<button type="submit">Save</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
views.py
def edit_profile(request):
if request.method == 'POST':
user_form = EditUserForm(request.POST, instance=request.user)
if all([user_form.is_valid(), profile_form.is_valid()]):
user_form.save()
return render(request, 'account/index.html')
else:
user_form = EditUserForm(instance=request.user)
args = {'user_form': user_form}
return render(request, 'account/edit_profile.html', args)
urls.py
urlpatterns = [
...
url(r'^edit/$', views.edit_profile, name='edit_profile'),
...
]
forms.py
class EditUserForm(forms.ModelForm):
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name'
)
Im using:
Python 3.6.3
Django 2.0.7
Windows 8.1
Bootstrap 3.3.6
JQuery 1.12.0
I think that variable form doesn't exist and you use in template just user_form not form variable
{% include "account/edit_profile.html" with form=form %}
Try use it:
{% include "account/edit_profile.html" with user_form=user_form %}
Maybe you could try the code I wrote and you can find it at django-bootstrap-modal-forms. You will be able to bind your form to the modal and all of the validation stuff will work out of the box.
You will create a trigger element opening the modal
Your selected form will be appended to the opened modal
On submit the form will be POSTed via AJAX request to form's URL
Unsuccessful POST request will return errors, which will be shown under form fields in modal
Successful POST request will redirects to selected success URL

django form is valid() fails

I am trying to create a registration form using django, when I submit my form the is valid() function fails and I am not sure why. I have my registration and login page all on one html page, although, I have called all the field names different names, eg login_username.
forms.py
class SignUpForm(forms.Form):
username = forms.CharField(label='Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Username'}))
conUsername = forms.CharField(label='Confirm Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Username'}))
firstName = forms.CharField(label='First Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Firstname'}))
lastName = forms.CharField(label='Last Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter LastName'}))
email = forms.CharField(label='Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Email','type':'email'}))
conEmail = forms.CharField(label='Confirm Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Email','type':'email'}))
password = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Enter Password'}))
conPassword = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Confirm Password'}))
views.py
def SignUp(request):
regForm = SignUpForm()
form = LoginForm()
if request.method == 'POST':
if regForm.is_valid():
username = regForm.cleaned_data('username')
print username
confirm_username = regForm.cleaned_data('conUsername')
first_name = regForm.cleaned_data('firstName')
last_name = regForm.cleaned_data('lastName')
email = regForm.cleaned_data('email')
confirm_email = regForm.cleaned_data('conEmail')
password = regForm.cleaned_data('password')
confirm_password = regForm.cleaned_data('conPassword')
#try:
#user = User.objects.get(username=request.POST['username'])
#return render(request, 'index.html',{'error_message':'username must be unique'})
#except User.DoesNotExist:
#user = User.objects.create_user(request.POST['username'], password=request.POST['password'])
#login(request, user)
#return render(request, 'index.html')
else:
return render(request,'index.html',{'username_error':'usernames didnt match','form':form,'regForm':regForm})
else:
return render(request, 'index.html',{'form':form,'regForm':regForm})
index.html
<form class="regForm" method="POST" action="{% url 'signup' %}">
{% csrf_token %}
{{username_error }}
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{regForm.error_message.username}}
{{ regForm.username }}
</div>
</div>
<div class="col-md-2 ">
<div class="form-group">
{{error_message.conUsername}}
{{ regForm.conUsername }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.firstName }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.lastName }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.email }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.conEmail }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.password }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.conPassword }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-9">
<div class="form-group">
<button type="submit" id="regBtn" class="btn btn-default">Submit</button>
</div>
</div>
</div>
</form>
Right now your form is always empty and therefore invalid. You forgot to add the request POST content to the form.
def SignUp(request):
# ...
if request.method == 'POST':
regForm = SignupForm(request.POST) # form needs content
if regForm.is_valid():
# ...
If you get stuck when calling .is_valid(), you can print(regForm.errors) to see what's up.
You have two main problems. Firstly, you are never passing the POST data to the form, so it can never be valid.
Secondly, for some reason you are ignoring everything that the form could tell you about why it is not valid, and always returning "usernames didn't match". What's more, you're not even doing anything to compare usernames, so that error message will never be accurate.
You should rework your view to follow the pattern as described in the documentation:
def SignUp(request):
if request.method == 'POST':
regForm = SignUpForm(request.POST)
if regForm.is_valid():
...
return redirect(somewhere)
else:
regForm = SignUpForm()
return render(request, 'index.html', {'regForm':regForm})
and in your template make sure you include {{ form.errors }} to show what the validation failures are.

Categories

Resources