I can imagine two possibilities: First, hide the different workflows from the database. Use an 'intelligent' string (json) to store different workflows with the same interface. Second, somehow create new tables for new workflows on the fly. The second seems to be the more elegant solution.
So this is my setup. Any idea / hint / solution is welcome.
Thanks!
Johannes
good luck!
--
Javier
from django.db import models
from django.contrib.auth.models import User
class Workflow(models.Model):
name = models.charfield(max_length = 200)
description = models.TextField()
class Step(models.Model):
workflow = models.ForeignKeyField(Workflow)
name = models.charfield()
order = models.SmallIntegerField()
taskdescription = models.TextField()
# suggestions for deadline / assignee
deadline = # implement as number of days from project.start_date or as number of days from start of current step. How?
assigned_to = models.ForeignKeyField(User, blank=True, null=True)
class Project(models.Model):
name = models.charfield()
workflow = models.ForeignKeyField(Workflow)
creation_date = models.DatetimeField(auto_now_add = True)
creator = models.ForeignKeyField(User)
start_date = models.DatetimeField() # in case start of project differs from creation date, default: creation date
class Task(models.Model):
project = models.ForeignKeyField(Project)
step = models.ForeignKeyField(Step)
deadline = models.DatetimeField() # initially computed from project.start_date, may be postponed by the user
assigned_to = models.ForeignKeyField(User, blank=True, null=True) # initially as given by Step, may be changed later
My Problem: I don't know how to approach this. Somehow I have to create Project / Jobs as indicated by the chosen Workflow. Unfortunately this a bit over my head at the moment: Could you give me rough directions on how to approach this? Drop some keywords what is needed to make this work?
Form
classes – one per
wizard page.') and I have to somehow know the chosen workflow in the first step... Is this possible with FormWizard? I could probably build a single Form for the multiple tasks, but how do I get the information on the chosen Workflow?WizardView.
get_cleaned_data_for_step
(step) . This seems to be the right deal...get_cleaned_data_for_step
(step) inside get_form_initial() (see: here).class JobWizard(CookieWizardView):
form_list = [forms.JobForm, forms.TaskForm]
def done(self, form_list, **kwargs):
do_something_with_the_form_data(form_list) # todo
return HttpResponseRedirect('/jobs/')
def get_form_initial(self, step):
current_step = self.storage.current_step
print(current_step)
print(self.steps.current)
print('\n')
if current_step == '1':
return self.initial_dict.get(step, {'deadline': timezone.now()})
return self.initial_dict.get(step, {'street': self.storage.current_step})
if current_step == '1' does not work as I would like it to. Once I submit the second form self.steps.current is incremented. So maybe I'm using the wrong variable: How do I determine if I'm in the second step? How can I rename the step names?
My goal at first is to load data from the first step and use it to preset some of the fields of the second step. Once that works I need to somehow create a formset for the different tasks...
Ok, so I set up the FormWizard, but it has some strange side effects. I implemented the process in three steps:
Choose a workflow
Specify information for the new Job (Adress, deadline, customer...)
Review deadlines and assigness for the different steps.
Problems occur in the third step:
I am thinking that FormWizard cannot handle the 'dynamic' changes I am doing: The third step is adjusted based on the chosen workflow in the first step. I read somewhere that this is can be an issue.
Maybe one of you can tell me where the mistake is? Any hint is appreciated.
My FormWizard:
class JobWizard(SessionWizardView):
form_list = [
('first', forms.WorkflowSelectForm),
('second', forms.JobForm),
('third', forms.TaskFormSet)
]
def done(self, form_list, **kwargs):
# store Job in database
# how do I access data in ValuesView?
forms = []
for form in form_list:
forms.append(form)
job = forms[1].save()
for form in forms[2]:
current_task = form.save(commit=False)
current_task.job = job
current_task.save()
return HttpResponseRedirect('/jobs/')
def get_form_initial(self, step):
if step is None:
step = self.steps.current
if step == 'second':
prev_data = self.storage.get_step_data('first')
return {'deadline': (timezone.now() + timezone.timedelta(days=30)).replace(hour=12, minute=0, second=0),
'workflow': Workflow.objects.get(pk = prev_data.get('first-workflow')),
'creator': self.request.user
}
if step == 'third':
first_step_data = self.get_cleaned_data_for_step('first')
second_step_data = self.get_cleaned_data_for_step('second')
steps = Step.objects.filter(workflow=first_step_data['workflow']).order_by('order')
# get total time
t_total = 0.
for step in steps:
t_total += step.time_fraction
deadline = second_step_data['deadline']
start_date = second_step_data['start_date']
job_duration = (deadline - start_date).total_seconds()
initial_data = []
task_deadline = start_date
for step in steps:
fraction = step.time_fraction / t_total
task_duration = fraction * job_duration
task_deadline = task_deadline + timezone.timedelta(seconds = task_duration)
assignee = step.assigned_to
data = {'deadline': task_deadline,
'assigned_to': assignee,
'step': step}
initial_data.append(data)
return initial_data
return self.initial_dict.get(step, {})
def get_form(self, step=None, data=None, files=None):
form = super(JobWizard, self).get_form(step, data, files)
if step is None:
step = self.steps.current
if step == 'third':
first_step_data = self.get_cleaned_data_for_step('first')
steps = Step.objects.filter(workflow=first_step_data['workflow']).order_by('order')
form.extra = len(steps)
return form
class JobForm(forms.ModelForm):
start_date = forms.DateTimeField(widget=forms.DateTimeInput, initial=timezone.now())
workflow = forms.ModelChoiceField(queryset=Workflow.objects.all(),widget=forms.TextInput(attrs={'readonly':'readonly'}))
creator = forms.ModelChoiceField(queryset=User.objects.all(),widget=forms.TextInput(attrs={'readonly':'readonly'}))
class Meta:
model = Job
exclude = ('creation_date', 'paused', 'paused_until', 'completed')
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ('job', 'finished', )
TaskFormSet = modelformset_factory(Task, form=TaskForm )
ModelForms
and
ModelFormSets. Additionally to
initial_dict
, the as_view()
method takes
an instance_dict
argument that should contain model instances for steps
based on ModelForm
and querysets for steps based on ModelFormSet
.'