use formsets for screening questions, create views for applying to jobs
This commit is contained in:
parent
7b33b832fe
commit
34b77e8a4e
8 changed files with 128 additions and 13 deletions
|
@ -1,5 +1,5 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Job, Application, Tag, Question
|
||||
from .models import Job, Application, Tag, Question, Answer
|
||||
|
||||
admin.site.register([Job, Application, Tag, Question])
|
||||
admin.site.register([Job, Application, Tag, Question, Answer])
|
||||
|
|
|
@ -2,7 +2,7 @@ from django import forms
|
|||
from django.forms import inlineformset_factory
|
||||
from dal.autocomplete import ModelSelect2Multiple
|
||||
|
||||
from .models import Job, Question
|
||||
from .models import Job, Question, Application, Answer
|
||||
|
||||
|
||||
class JobForm(forms.ModelForm):
|
||||
|
@ -23,6 +23,35 @@ class QuestionForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class ApplicationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Application
|
||||
exclude = ('job', 'applicant')
|
||||
|
||||
|
||||
class AnswerForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Answer
|
||||
fields = '__all__'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['text'].required = True
|
||||
self.fields['question'].disabled = True
|
||||
|
||||
@classmethod
|
||||
def inlineformset_factory(cls, extra=3):
|
||||
return inlineformset_factory(
|
||||
Application,
|
||||
Answer,
|
||||
form=cls,
|
||||
min_num=extra,
|
||||
max_num=extra,
|
||||
validate_min=True,
|
||||
can_delete=False,
|
||||
can_order=False)
|
||||
|
||||
|
||||
QuestionFormSet = inlineformset_factory(
|
||||
Job, Question, form=QuestionForm, can_delete=False, can_order=False)
|
||||
|
||||
|
|
23
jobs/migrations/0003_auto_20181020_0622.py
Normal file
23
jobs/migrations/0003_auto_20181020_0622.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.1.2 on 2018-10-20 06:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('jobs', '0002_auto_20181017_1104'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='application',
|
||||
name='cover_letter',
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='question',
|
||||
name='name',
|
||||
field=models.TextField(verbose_name='Question Title'),
|
||||
),
|
||||
]
|
|
@ -70,6 +70,7 @@ class Application(models.Model):
|
|||
User, related_name="applications", on_delete=models.CASCADE)
|
||||
job = models.ForeignKey(
|
||||
Job, related_name="applications", on_delete=models.CASCADE)
|
||||
cover_letter = models.TextField(blank=True)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
|
|
13
jobs/templates/jobs/application_form.html
Normal file
13
jobs/templates/jobs/application_form.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% extends 'base.html' %} {% block title %}Apply to job{% endblock %} {% load crispy_forms_tags %} {% block body_content %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<form method="POST" action=".">
|
||||
{% csrf_token %} {{ form |crispy }}
|
||||
<h4>Screening Questions</h4>
|
||||
{{ answer_form |crispy }}
|
||||
<input class="btn btn-primary submit" type="submit" value="Post Job" />
|
||||
</form>
|
||||
{{form.media}}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -22,7 +22,7 @@
|
|||
- {{question.name}} <br/>
|
||||
{% endfor %}
|
||||
<br/>
|
||||
<a href="#" class="card-link">Apply</a>
|
||||
<a href="{% url 'jobs:job_apply' job.pk %}" class="card-link">Apply</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
12
jobs/urls.py
12
jobs/urls.py
|
@ -1,17 +1,17 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
from .views import Index, JobCreate, JobList, JobDetail, ApplicationCreate
|
||||
from . import autocomplete as autocomplete_views
|
||||
|
||||
app_name = 'jobs'
|
||||
urlpatterns = [
|
||||
path('', views.Index.as_view(), name='index'),
|
||||
path('jobs/create/', views.JobCreate.as_view(), name='create'),
|
||||
path('jobs/', views.JobList.as_view(), name='list'),
|
||||
path('jobs/<int:pk>/detail/', views.JobDetail.as_view(), name='job_detail'),
|
||||
path('', Index.as_view(), name='index'),
|
||||
path('jobs/create/', JobCreate.as_view(), name='create'),
|
||||
path('jobs/', JobList.as_view(), name='list'),
|
||||
path('jobs/<int:pk>/detail/', JobDetail.as_view(), name='job_detail'),
|
||||
path('jobs/<int:job_pk>/apply/', ApplicationCreate.as_view(), name='job_apply'),
|
||||
]
|
||||
|
||||
|
||||
# autocomplete endpoints
|
||||
urlpatterns += [
|
||||
path(
|
||||
|
|
|
@ -4,8 +4,8 @@ from django.views.generic import (
|
|||
TemplateView, ListView, CreateView, DetailView
|
||||
)
|
||||
|
||||
from .models import Job
|
||||
from .forms import JobForm, QuestionFormSet
|
||||
from .models import Job, Application, Question
|
||||
from .forms import JobForm, QuestionFormSet, ApplicationForm, AnswerForm
|
||||
|
||||
|
||||
class Index(TemplateView):
|
||||
|
@ -59,3 +59,52 @@ class JobCreate(CreateView):
|
|||
self.get_context_data(
|
||||
form=form,
|
||||
question_form=question_form))
|
||||
|
||||
|
||||
class ApplicationCreate(CreateView):
|
||||
# TODO: restrict users from re-application
|
||||
model = Application
|
||||
form_class = ApplicationForm
|
||||
success_url = reverse_lazy("jobs:list")
|
||||
|
||||
def get_question_queryset(self):
|
||||
return Question.objects.filter(job_id=self.kwargs['job_pk']).order_by('id')
|
||||
|
||||
def get_answer_formset(self, *args):
|
||||
questions = self.get_question_queryset()
|
||||
return AnswerForm.inlineformset_factory(
|
||||
extra=questions.count())(initial=[{
|
||||
'question': q.id
|
||||
} for q in questions], *args)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.object = None
|
||||
form = self.get_form(self.get_form_class())
|
||||
answer_form = self.get_answer_formset()
|
||||
return self.render_to_response(
|
||||
self.get_context_data(form=form, answer_form=answer_form))
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = None
|
||||
form_class = self.get_form_class()
|
||||
form = self.get_form(form_class)
|
||||
answer_form = self.get_answer_formset(self.request.POST)
|
||||
if (form.is_valid() and answer_form.is_valid()):
|
||||
return self.form_valid(form, answer_form)
|
||||
else:
|
||||
return self.form_invalid(form, answer_form)
|
||||
|
||||
def form_valid(self, form, answer_form):
|
||||
self.object = form.save(commit=False)
|
||||
self.object.applicant = self.request.user
|
||||
self.object.job = Job.objects.get(id=self.kwargs['job_pk'])
|
||||
self.object.save()
|
||||
|
||||
answer_form.instance = self.object
|
||||
answer_form.save()
|
||||
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
def form_invalid(self, form, answer_form):
|
||||
return self.render_to_response(
|
||||
self.get_context_data(form=form, answer_form=answer_form))
|
||||
|
|
Loading…
Reference in a new issue