from django.urls import reverse_lazy from django.http import HttpResponseRedirect from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import (View, TemplateView, ListView, CreateView, DetailView) from django.views.generic.detail import SingleObjectMixin from django.contrib import messages from django.shortcuts import get_object_or_404, redirect from rules.contrib.views import PermissionRequiredMixin from django.contrib.auth import get_user_model from django.contrib.auth.decorators import login_required from .models import Job, Application, Question, JobMessage from .forms import JobForm, QuestionFormSet, ApplicationForm, AnswerForm, MessageForm import logging logger = logging.getLogger(__name__) User = get_user_model() class Index(TemplateView): template_name = 'jobs/index.html' def get_context_data(self, *args, **kwargs): context = super().get_context_data(*args, **kwargs) context['jobs'] = Job.objects.filter(active=True).order_by('-updated')[:6] return context class JobDetail(DetailView): context_object_name = 'job' model = Job class JobRenew(LoginRequiredMixin, PermissionRequiredMixin, SingleObjectMixin, View): model = Job permission_required = 'jobs.change_job' http_method_names = ['post'] def post(self, request, *args, **kwargs): job = self.get_object() job.renew() messages.add_message( request, messages.SUCCESS, 'Job has been renewed until {}.'.format( job.expires.isoformat(' ', 'seconds'))) return HttpResponseRedirect(job.get_absolute_url()) class JobCreate(LoginRequiredMixin, CreateView): model = Job form_class = JobForm success_url = reverse_lazy("jobs:job_list") 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() form.save_m2m() 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)) class ApplicationCreate(LoginRequiredMixin, CreateView): # TODO: restrict users from re-application model = Application form_class = ApplicationForm success_url = reverse_lazy("jobs:job_list") def get_question_queryset(self): # filter questions for particular job and order it so same queryset # can be used stably as initial params for GET and POST requests 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 = get_object_or_404(Job, id=self.kwargs['job_pk']) self.object.save() form.save_m2m() answer_form.instance = self.object answer_form.save() messages.add_message( self.request, messages.SUCCESS, 'Your application has been succesfully received.') 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)) class ApplicationList(LoginRequiredMixin, PermissionRequiredMixin, ListView): model = Application context_object_name = 'applications' permission_required = 'jobs.change_job' def get_permission_object(self): return get_object_or_404(Job, id=self.kwargs['job_pk']) def get_queryset(self): return super().get_queryset().filter(job_id=self.kwargs['job_pk']) class ListOwnApplications(ListView): model = Application context_object_name = 'applications' template_name = 'jobs/list_own_applications.html' def get_queryset(self): return Application.objects.filter(applicant=self.request.user) def get_context_data(self, **kwargs): context = super(ListOwnApplications, self).get_context_data(**kwargs) context['title'] = 'Your Applications' context['application_page'] = 'active' return context class ListJobApplications(ListView): model = Application context_object_name = 'applications' template_name = 'jobs/list_applications_others.html' def get_queryset(self): return Application.objects.filter(job__posted_by=self.request.user) def get_context_data(self, **kwargs): context = super(ListJobApplications, self).get_context_data(**kwargs) class ApplicationDetail(LoginRequiredMixin, DetailView): model = Application class MesssageInbox(LoginRequiredMixin, ListView): model = JobMessage context_object_name = 'jobmessage' def get_queryset(self): qs_list = [] qs = JobMessage.objects.filter(receiver=self.request.user).order_by('-date') lookup = set(qs.values_list('sender', flat=True)) for sender_id in lookup: for elem in qs: if elem.sender_id == sender_id: qs_list.append(elem.id) break return JobMessage.objects.filter(pk__in=qs_list).order_by('-date') def get_context_data(self, **kwargs): context = super(MesssageInbox, self).get_context_data(**kwargs) context['title'] = 'Messages Inbox' context['messages_page'] = 'active' return context class Conversation(LoginRequiredMixin, ListView): model = JobMessage context_object_name = 'jobmessage' template_name = 'jobs/conversation.html' def get_queryset(self): queryset1 = JobMessage.objects.filter( receiver=self.request.user, sender=self.kwargs['pk']) queryset2 = JobMessage.objects.filter( receiver=self.kwargs['pk'], sender=self.request.user) return queryset1.union(queryset2).order_by('date') def get_context_data(self, **kwargs): context = super(Conversation, self).get_context_data(**kwargs) context['form'] = MessageForm context['person'] = User.objects.get(id=self.kwargs['pk']) context['messages_page'] = 'active' return context class MyJobs(LoginRequiredMixin, ListView): model = Job context_object_name = 'jobs' template_name = 'jobs/job.html' def get_queryset(self): return Job.objects.filter(posted_by=self.request.user).order_by('expires') def get_context_data(self, **kwargs): context = super(MyJobs, self).get_context_data(**kwargs) context['title'] = 'Your jobs' context['my_jobs_page'] = 'active' return context @login_required() def send_message(request): form = MessageForm(request.POST) if form.is_valid(): user = User.objects.get(id=request.POST.get('receiver_id')) JobMessage.objects.create(sender=request.user, receiver=user, text=request.POST.get('text')) else: print("Error") return redirect('jobs:conversation', pk=request.POST.get('receiver_id')) @login_required() def change_status(request): try: job_obj = Job.objects.get(id=request.POST.get('job_id')) if job_obj.posted_by == request.user: if job_obj.active: job_obj.active = False else: job_obj.active = True job_obj.save() else: logger.error( "the user {} tried to toggle the job id {}. But it doesn't belong to him".format( request.user, request.POST.get('job_id')) ) except Job.DoesNotExist: logger.error( "the user {} tried to toggle the job id {} but it doesn't exist.".format( request.user, request.POST.get('job_id')) ) return redirect('jobs:my_jobs')