Skip to content

Instantly share code, notes, and snippets.

@RadicalPet
Last active September 6, 2018 11:51
Show Gist options
  • Save RadicalPet/534b50bae5fe74d7b5c29de1f25bf22a to your computer and use it in GitHub Desktop.
Save RadicalPet/534b50bae5fe74d7b5c29de1f25bf22a to your computer and use it in GitHub Desktop.
class CreateProjectView(LoginRequiredMixin, SessionWizardView):
template_name = 'gigui/project.html'
form_list = [
('1', KindSelectionForm),
('2', UrlGroupForm),
('3', CountriesForm),
('4', RulesKeywordsForm),
('5', OverviewForm),
]
def get(self, request, *args, **kwargs):
"""
This method handles GET requests.
If a GET request reaches this point, the wizard assumes that the user
just starts at the first step or wants to restart the process.
The data of the wizard will be resetted before rendering the first step
"""
self.storage.reset()
# reset the current step to the first step.
if 'cloned_pk' in self.kwargs:
self.storage.current_step = self.steps.last
else:
self.storage.current_step = self.steps.first
return self.render(self.get_form())
def _get_cloned_instance_initial_kwarg(self, pk):
instance = Project.objects.filter(pk=pk, owner=self.request.user).first()
if not instance:
raise Http404('User {self.request.user} does not have any checks.')
kwargs = vars(instance)
kwargs['url_groups'] = list(instance.url_groups.all())
kwargs['id'] = None
kwargs['name'] = f"Copy of {instance.name}"
return kwargs
def get_form_initial(self, step):
initial_dict = super().get_form_initial(step)
if 'cloned_pk' in self.kwargs:
initial_dict.update(
self._get_cloned_instance_initial_kwarg(
self.kwargs['cloned_pk']
)
)
return initial_dict
def get_form_instance(self, step):
if 'pk' in self.kwargs:
return get_object_or_404(
Project,
pk=self.kwargs['pk'],
owner=self.request.user,
)
def done(self, form_list, **kwargs):
project_form = list(form_list)[4]
cleaned_data = self.get_all_cleaned_data()
instance = project_form.save(commit=False)
instance.schedule = 'onetime'
instance.owner = self.request.user
instance.kind = cleaned_data['kind']
instance.countries = cleaned_data['countries']
instance.rules = cleaned_data.get('rules', [])
instance.keywords = cleaned_data.get('keywords', [])
instance.urls = list(itertools.chain(
*cleaned_data["url_groups"].values_list('urls', flat=True)
))
if "related_urls" in cleaned_data:
instance.related_urls = cleaned_data["related_urls"]
instance.priority_words = cleaned_data["priority_words"]
instance.save()
messages.add_message(self.request, messages.INFO, f'Your project "{instance.name}" was saved.')
instance.url_groups.set(cleaned_data["url_groups"])
return redirect('gigui:manage_checks')
def render_goto_step(self, step):
"""
If navigating to a step and prior step isn't filled,
render form errors
"""
# TODO: write tests!
if step > self.steps.current:
# the step before clicked tab must be filled
required_step = str(int(step) - 1)
can_continue = required_step in self.get_filled_steps()
if not can_continue:
return super().render_goto_step(self.steps.current)
return super().render_goto_step(step)
def get_filled_steps(self):
# TODO: write docstring and tests!
try:
return [
step
for step in ['1', '2', '3', '4', '5']
if self.get_cleaned_data_for_step(step) is not None
]
except UnknownKindError:
logger.warning('Cannot process steps without settings kind in step 1!')
return []
def get_context_data(self, form: ModelForm, **kwargs):
context = super().get_context_data(form=form, **kwargs)
context['filled_steps'] = self.get_filled_steps()
context['current_step'] = self.steps.current
if int(self.steps.current) >= 2:
if 'cloned_pk' in self.kwargs:
cleaned_data = self.get_form_initial('1')
cleaned_data = self.get_cleaned_data_for_step('1')
check_title = dict(PROJECT_TYPE_CHOICES)[cleaned_data['kind']]['title']
context['project_kind'] = cleaned_data['kind']
context['breadcrumbs'] = check_title
context['step4_name'] = ('Keywords' if cleaned_data['kind'] == 'popunder' else 'Rules')
if int(self.steps.current) == 2:
context['modal_form'] = UrlGroupModalForm
if int(self.steps.current) == 4:
if 'rules' in form.fields and not form.is_valid() and 'rules' in form.errors:
errors = []
for error in form.errors['rules']:
position, message = error.split(': ', 1)
position = re.findall('\d+', position)
errors.append((position, message))
context['rules_errors'] = json.dumps(errors)
if int(self.steps.current) == 5:
if 'cloned_pk' in self.kwargs:
context['url_groups'] = self.get_form_initial('2')['url_groups']
else:
context['url_groups'] = self.get_cleaned_data_for_step('2')['url_groups']
if 'cloned_pk' in self.kwargs:
selected_countries = self.get_form_initial('3')['countries']
else:
selected_countries = self.get_cleaned_data_for_step('3')['countries']
context['countries'] = [
(code, name)
for code, name in django_countries.countries
if code in selected_countries
]
if 'cloned_pk' in self.kwargs:
rules = self.get_form_initial('4').get('rules', {})
else:
rules = self.get_cleaned_data_for_step('4').get('rules', {})
context['rules'] = (
render_rules(rules)
if rules
else {}
)
if 'cloned_pk' in self.kwargs:
context['keywords'] = self.get_form_initial('4').get('keywords', [])
else:
context['keywords'] = self.get_cleaned_data_for_step('4').get('keywords', [])
return context
def get_form_kwargs(self, step=None):
kwargs = super().get_form_kwargs(step=step)
prev_step = self.get_prev_step(step)
kwargs['previous_step'] = prev_step
if step == "2":
step1_data = self.get_cleaned_data_for_step('1')
if step1_data:
kwargs["kind"] = self.get_cleaned_data_for_step('1')["kind"]
kwargs['owner'] = self.request.user
elif step == "4":
step1_data = self.get_cleaned_data_for_step('1')
if step1_data:
kwargs["kind"] = step1_data["kind"]
elif step == "5":
# pass own projects to check if project name is duplicated
qs = Project.objects.filter(owner=self.request.user)
if "pk" in self.kwargs:
qs = qs.exclude(pk=self.kwargs.get("pk", None))
kwargs["qs"] = qs
return kwargs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment