Reputation: 6027
I have seen plenty of similar posts, but nothing that had enough information to help me.
Disclaimer: I am very new to Django.
I am attempting to create an employment application for my company that will be hosted on a subdomain (e.g. jobs.mycompany.com) - this is my first real Django project. and what I am hoping to accomplish for the end-user has already been done in the admin section.
Basically, I broke the job application up into a few sections:
Here is the issue - I don't think I am putting this into one form correctly, and I also don't have a clue how to save all of these at one time. I have attempted to make form sets for Education
and Job_Experience
, but I don't think I am applying those correctly either.
Essentially, I want all of this to appear, and when the user clicks "submit" it creates all necessary records - applicant and availability being the only portions actually required.
Edit
To re-iterate: The admin panel is doing exactly what I want to achieve on the front end., but (on the front end) I have been unable to:
applicant
selector inputs go-awayapplicant
instances to non-applicant modelsCode below:
models.py
from django.db import models
from django import forms
from django.forms import ModelForm
from datetime import datetime
class Applicant(models.Model):
name = models.CharField(max_length=200)
city = models.CharField(max_length=200)
state = models.CharField(max_length=200)
zip = models.CharField(max_length=200)
social_security_number = models.CharField(max_length=200)
phone = models.CharField(max_length=200)
alt_phone = models.CharField(max_length=200, blank=True)
us_citizen = models.BooleanField()
committed_felony = models.BooleanField()
is_16 = models.BooleanField()
has_drivers_license = models.BooleanField()
is_disabled = models.BooleanField()
prev_employed = models.BooleanField()
felony_explanation = models.TextField(blank=True)
disabled_explanation = models.TextField(blank=True)
prev_employment_manager = models.CharField(max_length=200, blank=True)
prev_employment_year = models.CharField(max_length=4, blank=True)
skills = models.TextField()
def __unicode__(self):
return self.name
class Education(models.Model):
GED = 'GED'
HIGH_SCHOOL = 'HIG'
JUNIOR_COLLEGE = 'JUN'
UNIVERSITY = 'UNI'
TYPE_OF_SCHOOL_CHOICES = (
(GED, 'GED'),
(HIGH_SCHOOL, 'High School'),
(JUNIOR_COLLEGE, 'Junior College'),
(UNIVERSITY, 'University'),
)
type = models.CharField(
max_length=3,
choices=TYPE_OF_SCHOOL_CHOICES,
default=HIGH_SCHOOL
)
school_name = models.CharField(max_length=200)
school_city = models.CharField(max_length=200)
school_state = models.CharField(max_length=200)
graduated = models.BooleanField()
graduation_year = models.CharField(max_length=4)
applicant = models.ForeignKey(Applicant)
class Job_Experience(models.Model):
FULL_TIME = 'F'
PART_TIME = 'P'
FTPT_CHOICES = (
(FULL_TIME, 'Full Time'),
(PART_TIME, 'Part Time'),
)
organization_name = models.CharField(max_length=200)
organization_city = models.CharField(max_length=200)
organization_state = models.CharField(max_length=200)
supervisor_name = models.CharField(max_length=200)
supervisor_phone = models.CharField(max_length=200)
supervisor_contact_allowed = models.BooleanField()
currently_employed = models.BooleanField()
start_date = models.DateField()
end_date = models.DateField()
starting_title = models.CharField(max_length=200)
ending_title = models.CharField(max_length=200)
start_salary = models.CharField(max_length=20)
end_salary = models.CharField(max_length=20)
reason_for_leaving = models.TextField()
full_time_part_time = models.CharField(
max_length = 1,
choices = FTPT_CHOICES,
default = PART_TIME
)
applicant = models.ForeignKey(Applicant)
class Availability (models.Model):
NOT_AVAILABLE = 'XX'
OPEN_AVAILABILITY = 'OP'
AVAILABLE_BETWEEN = 'AB'
AVAILABILITY_CHOICES = (
(NOT_AVAILABLE, 'Not Available'),
(OPEN_AVAILABILITY, 'Available All Day'),
(AVAILABLE_BETWEEN, 'Available Between Certain Hours'),
)
mon_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
mon_hours_start = models.CharField(max_length = 10)
mon_hours_end = models.CharField(max_length = 10)
tue_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
tue_hours_start = models.CharField(max_length = 10)
tue_hours_end = models.CharField(max_length = 10)
wed_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
wed_hours_start = models.CharField(max_length = 10)
wed_hours_end = models.CharField(max_length = 10)
thu_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
thu_hours_start = models.CharField(max_length = 10)
thu_hours_end = models.CharField(max_length = 10)
fri_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
fri_hours_start = models.CharField(max_length = 10)
fri_hours_end = models.CharField(max_length = 10)
fri_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
sat_hours_start = models.CharField(max_length = 10)
sat_hours_end = models.CharField(max_length = 10)
sat_availability = models.CharField(
max_length = 2,
choices = AVAILABILITY_CHOICES,
default = NOT_AVAILABLE
)
sun_hours_start = models.CharField(max_length = 10)
sun_hours_end = models.CharField(max_length = 10)
applicant = models.OneToOneField(Applicant)
# Forms
class ApplicantForm(ModelForm):
class Meta:
model = Applicant
class EducationForm(ModelForm):
class Meta:
model = Education
class JobExperienceForm(ModelForm):
class Meta:
model = Job_Experience
class AvailabilityForm(ModelForm):
class Meta:
model = Availability
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import Context, loader
from applications.models import Applicant, Education, Job_Experience, Availability, ApplicantForm, EducationForm, JobExperienceForm, AvailabilityForm
from django.forms.formsets import formset_factory
def index(request):
education_formset = formset_factory(EducationForm, extra=3)
message = 'Forms have not been submitted.'
if request.method == 'POST':
applicant_form = ApplicantForm(request.POST)
education_form = education_formset(request.POST)
if applicant_form.is_valid() and education_form.is_valid():
applicant_form.save()
education_form.applicant = applicant_form
message = 'Forms are valid.'
else:
message = 'Forms are not valid.'
else:
applicant_form = ApplicantForm()
education_form = education_formset()
return render(request,
'applications/index.html',
{
'applicant_form' : applicant_form,
'education_form' : education_form,
'message' : message
}
)
admin.py
from django.contrib import admin
from applications.models import Applicant, Education, Job_Experience, Availability
class EducationInline(admin.StackedInline):
model = Education
extra = 3
class JobExperienceInline(admin.StackedInline):
model = Job_Experience
extra = 3
class AvailabilityInline(admin.StackedInline):
model = Availability
class ApplicantAdmin(admin.ModelAdmin):
inlines = [EducationInline, JobExperienceInline, AvailabilityInline]
admin.site.register(Applicant, ApplicantAdmin)
index.html
<h1>Employment Application</h1>
<p>Please enter your information into the fields below.</p>
<hr />
<p>{{ message }}</p>
<hr />
<form action="{% url 'applications:index' %}" method="post">
{% csrf_token %}
{{ applicant_form.as_p }}
<hr />
{{ education_form.as_p }}
<input type="submit" />
</form>
Upvotes: 1
Views: 622
Reputation: 10167
I realize this is a couple months old, and maybe you've solved this already using Django or are using something else now, but you were very close. The basic view pattern for your use case is to:
Something like the following:
def index(request):
EducationFormSet = formset_factory(
Application,
Education,
form=EducationForm,
extra=3,
)
if request.method == 'POST':
application_form = ApplicationForm(request.POST)
if application_form.is_valid():
application = application_form.save(commit=False)
education_formset = EducationFormSet(request.POST, instance=application)
if education_formset.is_valid():
application.save()
education_formset.save()
return HttpResponseRedirect(reverse('thanks_and_good_luck_view'))
else:
education_formset = EducationFormSet(request.POST)
else:
application_form = ApplicationForm()
education_formset = EducationFormSet()
return render_to_response(
'applications/index.html',
{
'application_form': application_form,
'education_formset': education_formset,
},
context_instance=RequestContext(request)
)
The tricky bit here is the commit=False
when saving the parent form. This allows you to get an uncommitted instance of the parent model to use for the child model instances in the formset.
Upvotes: 1
Reputation: 174614
As I understand your question, you want the same admin inline functionality on your front end.
The django admin application uses customized jquery for its front end. Part of that is the automatic generation of sub forms.
To get started with that on your own front end, start with the formsets
section in the documentation. This will give you the basic idea on how multiple sub-forms work in the view. Then you can move to inline formsets
which is what the admin uses to render its forms.
For the javascript part, you can use django-dynamic-formset
or something more comprehensive like crispy forms which provides better rendering and support for dynamic inlines.
Upvotes: 0