From 25f045a68cc3fd13694cdb9c13bba6d19f994951 Mon Sep 17 00:00:00 2001 From: Aatish Neupane Date: Wed, 17 Oct 2018 17:03:34 +0545 Subject: [PATCH] create Question and Answer model, use inline formsets in JobCreate --- jobs/admin.py | 4 +- jobs/forms.py | 22 +++++---- jobs/migrations/0002_auto_20181017_1104.py | 53 ++++++++++++++++++++++ jobs/models.py | 27 +++++++++++ jobs/templates/jobs/job_form.html | 9 +++- jobs/views.py | 39 ++++++++++++++-- 6 files changed, 138 insertions(+), 16 deletions(-) create mode 100644 jobs/migrations/0002_auto_20181017_1104.py diff --git a/jobs/admin.py b/jobs/admin.py index 0a3ca75..617a6d1 100644 --- a/jobs/admin.py +++ b/jobs/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Job, Application, Tag +from .models import Job, Application, Tag, Question -admin.site.register([Job, Application, Tag]) \ No newline at end of file +admin.site.register([Job, Application, Tag, Question]) \ No newline at end of file diff --git a/jobs/forms.py b/jobs/forms.py index eaff056..2d5f9fe 100644 --- a/jobs/forms.py +++ b/jobs/forms.py @@ -1,9 +1,8 @@ from django import forms -from crispy_forms.helper import FormHelper -from crispy_forms.layout import Submit +from django.forms import inlineformset_factory from dal.autocomplete import ModelSelect2Multiple -from .models import Job +from .models import Job, Question class JobForm(forms.ModelForm): @@ -14,8 +13,15 @@ class JobForm(forms.ModelForm): 'tags': ModelSelect2Multiple(url='jobs:tag-autocomplete') } - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.helper = FormHelper() - self.helper.form_method = 'post' - self.helper.add_input(Submit('submit', 'Post Job')) + +class QuestionForm(forms.ModelForm): + class Meta: + model = Question + fields = '__all__' + widgets = { + 'name': forms.widgets.TextInput() + } + + +QuestionFormSet = inlineformset_factory( + Job, Question, form=QuestionForm, can_delete=False, can_order=False) \ No newline at end of file diff --git a/jobs/migrations/0002_auto_20181017_1104.py b/jobs/migrations/0002_auto_20181017_1104.py new file mode 100644 index 0000000..95e6a9d --- /dev/null +++ b/jobs/migrations/0002_auto_20181017_1104.py @@ -0,0 +1,53 @@ +# Generated by Django 2.1.2 on 2018-10-17 11:04 + +from django.db import migrations, models +import django.db.models.deletion +import jobs.date_utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('jobs', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Answer', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('application', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='jobs.Application')), + ], + ), + migrations.CreateModel( + name='Question', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.TextField()), + ], + ), + migrations.AlterModelOptions( + name='tag', + options={'ordering': ['name']}, + ), + migrations.AlterField( + model_name='job', + name='expires', + field=models.DateTimeField(default=jobs.date_utils.after_30_days, editable=False), + ), + migrations.AddField( + model_name='question', + name='job', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questions', to='jobs.Job'), + ), + migrations.AddField( + model_name='answer', + name='question', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='jobs.Question'), + ), + migrations.AlterUniqueTogether( + name='answer', + unique_together={('question', 'application')}, + ), + ] diff --git a/jobs/models.py b/jobs/models.py index c56bbe8..9d21339 100644 --- a/jobs/models.py +++ b/jobs/models.py @@ -49,6 +49,16 @@ class Job(models.Model): return self.title +class Question(models.Model): + ''' A model to hold screening questions for a job post ''' + name = models.TextField() + job = models.ForeignKey( + Job, related_name='questions', on_delete=models.CASCADE) + + def __str__(self): + return self.name + + class Application(models.Model): ''' A model representing applications to job ''' @@ -64,3 +74,20 @@ class Application(models.Model): def __str__(self): return "{0} - Job: {1}".format(self.applicant, self.job) + + +class Answer(models.Model): + ''' a model to hold answers for screening questions by job applicants ''' + + question = models.ForeignKey( + Question, related_name='answers', on_delete=models.CASCADE) + application = models.ForeignKey( + Application, related_name='answers', on_delete=models.CASCADE + ) + text = models.TextField() + + class Meta: + unique_together = ('question', 'application') + + def __str__(self): + return "Answer for : {0} - {1}".format(self.question, self.application) diff --git a/jobs/templates/jobs/job_form.html b/jobs/templates/jobs/job_form.html index a878737..e0ac965 100644 --- a/jobs/templates/jobs/job_form.html +++ b/jobs/templates/jobs/job_form.html @@ -6,7 +6,14 @@ {% block body_content %}
- {% crispy form %} +
+ {% csrf_token %} + {{ form |crispy }} +

Screening Questions

+ {{ question_form |crispy }} + +
+ {{form.media}}
{% endblock %} \ No newline at end of file diff --git a/jobs/views.py b/jobs/views.py index 138dc58..9bcb834 100644 --- a/jobs/views.py +++ b/jobs/views.py @@ -1,10 +1,11 @@ from django.urls import reverse_lazy +from django.http import HttpResponseRedirect from django.views.generic import ( TemplateView, ListView, CreateView ) from .models import Job -from .forms import JobForm +from .forms import JobForm, QuestionFormSet class Index(TemplateView): @@ -21,7 +22,35 @@ class JobCreate(CreateView): form_class = JobForm success_url = reverse_lazy("jobs:list") - def form_valid(self, form): - obj = form.save(commit=False) - obj.posted_by = self.request.user - return super().form_valid(form) + def get(self, request, *args, **kwargs): + self.object = None + form = self.get_form(self.get_form_class()) + question_form = QuestionFormSet() + return self.render_to_response( + self.get_context_data(form=form, question_form=question_form)) + + def post(self, request, *args, **kwargs): + self.object = None + form_class = self.get_form_class() + form = self.get_form(form_class) + question_form = QuestionFormSet(self.request.POST) + if (form.is_valid() and question_form.is_valid()): + return self.form_valid(form, question_form) + else: + return self.form_invalid(form, question_form) + + def form_valid(self, form, question_form): + self.object = form.save(commit=False) + self.object.posted_by = self.request.user + self.object.save() + + question_form.instance = self.object + question_form.save() + + return HttpResponseRedirect(self.get_success_url()) + + def form_invalid(self, form, question_form): + return self.render_to_response( + self.get_context_data( + form=form, + question_form=question_form))