I am trying to create a employee using a form. I want that after pressing the submit buttom data saves to employee list table and the page redirect to employee list table also. When I see the error log it shows Method Not Allowed (POST) . I think my code is fine but somehow it is not working.
employee_add_form.html:
{% extends 'base.html' %}
{% block content %}
{% load static %}
<link rel="stylesheet" href="{% static 'employee/css/master.css' %}">
{% load bootstrap4 %}
<div class="">
<form class="form" action="{% url 'employee:employee-list' %}" method="post" id="employee_add_form">
{% csrf_token %}
<!-- {% bootstrap_css %}-->
{% bootstrap_javascript jquery='full' %}
{{ form.media }}
{{ form.non_field_errors }}
<div class="container">
<label for=""><b>Personal Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.first_name.errors }}
<label for="">First Name</label>
{{ form.first_name}}
</div>
<div class="col">
{{ form.last_name.errors }}
<label for="">Last Name</label>
{{ form.last_name}}
</div>
<div class="col">
{{ form.photo_id.errors }}
<label for="">Photo ID</label>
{{ form.photo_id }}
</div>
</div>
<div class="form-row inline">
<div class="col-4">
{{ form.gender.errors }}
<label for="">Gender</label>
{{ form.gender }}
</div>
<div class="col-4">
{{ form.blood_group.errors }}
<label for="">Blood Group</label>
{{ form.blood_group }}
</div>
<div class="col-4">
{{ form.religion.errors }}
<label for="">Religion</label>
{{ form.religion }}
</div>
</div>
<div class="form-row">
<div class="col">
{{ form.birth_date.errors }}
<label for="">Date of Birth</label>
{{ form.birth_date }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Contact Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.email.errors }}
<label for="">Email</label>
{{ form.email }}
</div>
<div class="col">
{{ form.phone_number.errors }}
<label for="">Phone Number</label>
{{ form.phone_number }}
</div>
<div class="col">
{{ form.address.errors }}
<label for="">Address</label>
{{ form.address }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Work Info</b></label>
<div class="border">
<div class="form-row">
<div class="col">
{{ form.e_id.errors }}
<label for="">Employee ID</label>
{{ form.e_id }}
</div>
<div class="col">
{{ form.designation.errors }}
<label for="">Designation</label>
{{ form.designation }}
</div>
<div class="col">
{{ form.department.errors }}
<label for="">Department</label>
{{ form.department }}
</div>
</div>
<div class="form-row">
<div class="col">
{{ form.join_date.errors }}
<label for="">Joining Date</label>
{{ form.join_date }}
</div>
</div>
</div>
</div>
<div class="container">
<label for=""><b>Attachments</b></label>
<div class="border">
<div class="form-group">
<div class="col">
{{ form.cv.errors }}
<label for="">CV</label>
{{ form.cv }}
</div>
<div class="col">
{{ form.document.errors }}
<label for="">Documents</label>
{{ form.document }}
</div>
<div class="col">
{{ form.photo.errors }}
<label for="">Image</label>
{{ form.photo }}
</div>
</div>
</div>
</div>
<div class="container">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
{% endblock %}
views.py:
class EmployeeAddView(CreateView):
"""
Created new employee
"""
template_name = 'employee/employee_add_form.html'
form_class = EmployeeAddModelForm
# queryset = Employee.objects.all()
model = Employee
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('employee:employee-list')
return render(request, self.template_name, {'form': form})
urls.py:
from django.urls import path
from django.urls import reverse
from . views import (
EmployeeListView,
EmployeeAddView,
EmployeeDetailView,
EmployeeUpdateView,
EmployeeDeleteView,
)
app_name = 'employee'
urlpatterns = [
path('employee-list/', EmployeeListView.as_view(), name='employee-list'),
path('employee-add/', EmployeeAddView.as_view(), name='employee-add'),
path('employee-list/<int:id>/', EmployeeDetailView.as_view(), name='employee-detail'),
path('employee-list/<int:id>/update/', EmployeeUpdateView.as_view(), name='employee-update'),
path('employee-list/<int:id>/delete/', EmployeeDeleteView.as_view(), name='employee-delete'),
]
forms.py:
from django import forms
from core.models import Employee
from bootstrap_datepicker_plus import DatePickerInput
class EmployeeAddModelForm(forms.ModelForm):
use_required_attribute = False
class Meta:
model = Employee
fields = [
'e_id',
'first_name',
'last_name',
'gender',
'religion',
'blood_group',
'birth_date',
'photo_id',
'designation',
#'employee_type',
'join_date',
'address',
'phone_number',
'email',
#'supervisor',
'bank_account_no',
'department',
#'salary_type',
'cv',
'document',
'photo',
]
widgets = {
'birth_date': DatePickerInput(),
'join_date': DatePickerInput(),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Edit label:
self.fields['e_id'].label = 'Employee ID'
self.fields['cv'].label = 'CV'
# Remove help suggestion
for fieldname in ['e_id',
'first_name',
'last_name',
'gender',
'religion',
'blood_group',
'birth_date',
'photo_id',
'designation',
#'employee_type',
'join_date',
'address',
'phone_number',
'email',
#supervisor',
'bank_account_no',
'department',
#'salary_type',
'cv',
'document',
'photo']:
self.fields[fieldname].help_text = None
Your form is POST-ing to wrong URL
<form class="form" action="{% url 'employee:employee-list' %}" method="post" id="employee_add_form">
instead should be
<form class="form" action="{% url 'employee:employee-add' %}" method="post" id="employee_add_form">
If you are using class based view than you can do this.
class EmployeeAddView(CreateView):
template_name = 'employee/employee_add_form.html'
form_class = EmployeeAddModelForm
queryset = Employee.objects.all()
success_url = '/employee-list'
def form_valid(self, form):
print(form.cleaned_data)
return super().form_valid(form)
Change method="post" to method="POST" it should work. I had a similar problem with CBV. This worked for me.
Related
I posted this question earlier but it was then linked to a similar question which don't provide the required solution and was then closed for answering.
So I have created a Flask Application that tracks the movement of products from one location to another while I make movements via the Flask App the form doesn't get validated I tried adding {{ form.hidden_tag() }} and {{ form.csrf_token }} to the html file that takes input from the user.
If I run this application from the terminal on my command line the form is validated and gets added to the database but if I run the flask app and submit the form in the browser it doesn't.
here is my code for the same
class MovementForm(FlaskForm):
to_location = SelectField('To Location', coerce=int)
from_location = SelectField('From Location', coerce=int)
product = SelectField('Product')
quantity = IntegerField('Quantity')
add_movement = SubmitField('Add Movement')
#app.route('/movements',methods=["GET","POST"])
def add_movements():
form = MovementForm()
form.to_location.choices = [(location.id, location.location_name) for location in Location.query.all()]
form.from_location.choices = [(location.id, location.location_name) for location in Location.query.all()]
form.product.choices = [(product.id, product.product_name) for product in Product.query.all()]
form.from_location.choices.insert(0, (0, 'None'))
if form.validate_on_submit():
new_movement = Movement(to_location_id=form.to_location.data, from_location_id=form.from_location.data, product_id=form.product.data, quantity=form.quantity.data)
db.session.add(new_movement)
db.session.commit()
flash('Product has been moved!', 'success')
return redirect(url_for('add_movements'))
return render_template('add_movements.html', form=form)
Here is my html file
<form action="/movements" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
</form>
What's wrong here?
Try to remove to change in the HTML form the form's action.
<form action="" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
</form>
Does this solve the issue?
Also What I suggest you is to add the Flash message into the HTML, because I see that once the Form is submitted it returns back to the 'add_movements' function. Therefore add this:
<div>
{% for msg in get_flashed_messages%}
<h1>{{msg}}</h1>
{% endfor %}
</div>
<form action="" method="post">
{{ form.hidden_tag() }}
{{ form.csrf_token }}
<div class="row">
<div class="form-group col">
{{ form.from_location.label(class="form-control-label") }}
{{ form.from_location(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.to_location.label(class="form-control-label") }}
{{ form.to_location(class="form-control form-control-lg") }}
</div>
</div>
<div class="row">
<div class="form-group col">
{{ form.product.label(class="form-control-label") }}
{{ form.product(class="form-control form-control-lg") }}
</div>
<div class="form-group col">
{{ form.quantity.label(class="form-control-label") }}
{{ form.quantity(class="form-control form-control-lg") }}
</div>
</div>
<div class="form-group">
{{ form.add_movement(class="btn btn-outline-info") }}
</div>
#EDIT
I noticed that something is missing in the product field once coerce in missing:
class MovementForm(FlaskForm):
to_location = SelectField('To Location', coerce=int)
from_location = SelectField('From Location', coerce=int)
product = SelectField('Product', coerce=int)
quantity = IntegerField('Quantity')
add_movement = SubmitField('Add Movement')
EDIT #2
In case you run in this kind of issues (which happens all the time) I suggest you to add a print statements and a If/Else clause as well. This will dramatically help you where the issue is ( The issue on your type of problem you posted is that you 'don't see it') and will give you 'eyes.'
For example this is what I would have done:
#app.route('/movements',methods=["GET","POST"])
def add_movements():
form = MovementForm()
form.to_location.choices = [(location.id, location.location_name) for
location in Location.query.all()]
form.from_location.choices = [(location.id, location.location_name)
for location in Location.query.all()]
form.product.choices = [(product.id, product.product_name) for product
in Product.query.all()]
form.from_location.choices.insert(0, (0, 'None'))
if form.validate_on_submit():
print('Form Ok') #if you see the 'Form ok' to see if is validated
new_movement = Movement(to_location_id=form.to_location.data,
from_location_id=form.from_location.data,
product_id=form.product.data, quantity=form.quantity.data)
db.session.add(new_movement)
db.session.commit()
flash('Product has been moved!', 'success')
return redirect(url_for('add_movements'))
else:
print('Form Not Ok') #If you see this printed then you see that
#is not validated
return render_template('add_movements.html', form=form)
I have a Django ModelForm as below:
class MeasurementForm(ModelForm):
class Meta:
model = Measurement
fields = ['weight', 'height', 'back_length', 'side_length', 'girth', 'food_consumption', 'measurement_type']
I use the form in a create_measurement view as below:
def create_measurement(request, pup_id):
pup = Pup.objects.get(id=pup_id)
if request.method == 'POST':
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measured_pup = pup
measurement.save()
return redirect('/pup/{{ pup.id }}')
else:
form = MeasurementForm()
return render(request, 'create_measurement.html', {'form': form, 'pup_id': pup.id})
This goes with the html:
<form action="/{{ pup_id }}/create-measurement/" method="POST">
{% csrf_token %}
{% load widget_tweaks %}
<small class="text-danger">{{ form.non_field_errors }}</small>
<div class="row">
<div class="form-group col-md-6">
<small class="text-danger">{{ form.weight.errors }}</small>
<label for="{{ form.weight.id_for_label }}">Weight:</label>
{{ form.weight|add_class:"form-control" }}
</div>
<div class="form-group col-md-6">
<small class="text-danger">{{ form.height.errors }}</small>
<label for="{{ form.height.id_for_label }}">Height:</label>
{{ form.height|add_class:"form-control" }}
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<small class="text-danger">{{ form.back_length.errors }}</small>
<label for="{{ form.back_length.id_for_label }}">Back Length:</label>
{{ form.back_length|add_class:"form-control" }}
</div>
<div class="form-group col-md-6">
<small class="text-danger">{{ form.side_length.errors }}</small>
<label for="{{ form.side_length.id_for_label }}">Side Length:</label>
{{ form.side_length|add_class:"form-control" }}
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<small class="text-danger">{{ form.girth.errors }}</small>
<label for="{{ form.girth.id_for_label }}">Girth:</label>
{{ form.girth|add_class:"form-control" }}
</div>
<div class="form-group col-md-6">
<small class="text-danger">{{ form.measurement_type.errors }}</small>
<label for="{{ form.measurement_type.id_for_label }}">Measurement Type:</label>
{{ form.measurement_type|add_class:"form-control" }}
</div>
</div>
<button type="submit" class="btn btn-primary">Add Measurement</button>
</form>
When submitting the form I receive a status 200 (OK) from the console, however the form does not save and I am not redirected to the pup details page as I should be. What am I doing wrong here?
{{ pup.id }} is Django template syntax and is supposed to use with template engines. If you need simple variable interpolation, you can use f-string instead
def create_measurement(request, pup_id):
pup = Pup.objects.get(id=pup_id)
if request.method == 'POST':
form = MeasurementForm(request.POST)
if form.is_valid():
...
return redirect(f'/pup/{pup.id}')
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
I have problem with django-floppyforms. On the page, the form appears as it should - it is a dedicated front-end. However, the validation and sending of the form does not work. I do not know why.
My form with django-floppyforms:
from events import models
import floppyforms.__future__ as forms
class ParticipantForm(forms.ModelForm):
class Meta:
model = models.Participant
fields = ('event', 'first_name', 'last_name', 'company', 'street', 'post_code', 'city', 'email', 'phone_number',)
widgets = {'event': forms.HiddenInput}
Here is my form on register template:
<form id="anmelde-form" class="form-default" action="" method="post">{% csrf_token %}
{% form form using "floppyforms/event_detail.html" %}
<input type="submit" value="{% blocktrans %}Anmelden{% endblocktrans %}" class="btn btn-default bg-mid-gray" />
</form>
Here is templete included on register template floppyforms/event_detail.html:
{% load floppyforms %}{% block formconfig %}{% formconfig row using "floppyforms/rows/p.html" %}{% endblock %}
{% form form using %}
<div class="form-input">
<label for="prename">First name*</label>
{% formfield form.first_name %}
</div>
<div class="form-input">
<label for="surname">Last name*</label>
{% formfield form.last_name %}
</div>
<div class="form-input">
<label for="company">Company</label>
{% formfield form.company %}
</div>
<div class="form-input">
<label for="street">Street</label>
{% formfield form.street %}
</div>
<div class="form-input-wrapper">
<div class="form-input small-4 columns">
<label for="area-code">Post code</label>
{% formfield form.post_code %}
</div>
<div class="form-input small-8 columns">
<label for="city">City</label>
{% formfield form.city %}
</div>
</div>
<div class="form-input">
<label for="mail">E-Mail*</label>
{% formfield form.email %}
</div>
<div class="form-input">
<label for="phone">Telefon*</label>
{% formfield form.phone_number %}
</div>
{% endform %}
I have this ModelForm and I am trying to render a class in the html, however it won't work.
Here is what I have:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = (
'first_name',
'profile_pic',
'location',
'title',
'user_type',
'website',
'twitter',
'dribbble',
'github'
)
widget = {
'first_name':forms.Textarea(attrs={'class':'form-control'}),
'profile_pic':forms.TextInput(attrs={'class':'form-control'}),
'location':forms.TextInput(attrs={'class':'form-control'}),
'title':forms.TextInput(attrs={'class':'form-control'}),
'user_type':forms.TextInput(attrs={'class':'form-control'}),
'website':forms.URLInput(attrs={'class':'form-control'}),
'twitter':forms.TextInput(attrs={'class':'form-control'}),
'dribbble':forms.TextInput(attrs={'class':'form-control'}),
'github':forms.TextInput(attrs={'class':'form-control'}),
}
I have tried this...
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
class Meta:
model = UserProfile
fields = (
'first_name',
'profile_pic',
'location',
'title',
'user_type',
'website',
'twitter',
'dribbble',
'github'
)
EDIT
Here are the two ways I have tried rendering forms in the template
Automatic:
<div class="form-group">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input class="btn btn-primary" type="submit" value="Save" />
</form>
</div>
Manually rendering each field:
Please excuse the bootstrap setup I have here.
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form-row">
<div class="form-group col">
{{ form.first_name.errors }}
<label for="{{ form.first_name.id_for_label }}">Name:</label>
{{ form.first_name }}
{{ form.profile_pic.errors }}
<label for="{{ form.profile_pic.id_for_label }}">Profile Picture:</label>
{{ form.profile_pic }}
</div>
<div class="col-3">
{{ form.location.errors }}
<label for="{{ form.location.id_for_label }}">Location:</label>
{{ form.location }}
</div>
</div>
<div class="fieldWrapper">
{{ form.location.errors }}
<label for="{{ form.location.id_for_label }}">Location:</label>
{{ form.location }}
</div>
<div class="fieldWrapper">
{{ form.title.errors }}
<label for="{{ form.title.id_for_label }}">Title:</label>
{{ form.title }}
</div>
<div class="fieldWrapper">
{{ form.user_type.errors }}
<label for="{{ form.user_type.id_for_label }}">User Type:</label>
{{ form.user_type }}
</div>
<div class="fieldWrapper">
{{ form.website.errors }}
<label for="{{ form.website.id_for_label }}">Website:</label>
{{ form.website }}
</div>
<div class="fieldWrapper">
{{ form.about.errors }}
<label for="{{ form.about.id_for_label }}">About:</label>
{{ form.about }}
</div>
<div class="fieldWrapper">
{{ form.twitter.errors }}
<label for="{{ form.twitter.id_for_label }}">Twitter:</label>
{{ form.twitter }}
</div>
<div class="fieldWrapper">
{{ form.dribbble.errors }}
<label for="{{ form.dribbble.id_for_label }}">Dribbble:</label>
{{ form.dribbble }}
</div>
<div class="fieldWrapper">
{{ form.github.errors }}
<label for="{{ form.github.id_for_label }}">Github:</label>
{{ form.github }}
</div>
<input class="btn btn-primary" type="submit" value="Save" />
</form>
The view:
class UserEditProfileView(LoginRequiredMixin,UpdateView):
login_url = '/login/'
model = UserProfile
fields = [
'first_name',
'profile_pic',
'location',
'title',
'user_type',
'about',
'website',
'twitter',
'dribbble',
'github'
]
template_name_suffix = '_edit_form'
def get_success_url(self):
userid = self.kwargs['pk']
return reverse_lazy('users:user_profile',kwargs={'pk': userid})
Neither of them work, I have been looking all over for how to get this to work but I can't seem to figure it out.
By default UpdateView generates a form for you, which is used further.
Specify your custom form class like that:
class UserEditProfileView(LoginRequiredMixin,UpdateView):
model = UserProfile
form_class = UserProfileForm
It is hidden in the docs. You need to browse through the mixins used by the UpdateView. The FormMixin provides this attribute for you.
If you don't provide one - ModelForm is smart enought to create one.