Skip to content

Instantly share code, notes, and snippets.

@coderanger
Created March 21, 2011 04:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coderanger/879019 to your computer and use it in GitHub Desktop.
Save coderanger/879019 to your computer and use it in GitHub Desktop.
from django import forms
from django.core.exceptions import ValidationError
from commis.api.cookbook.models import CookbookRecipe
from commis.api.node.models import Node
from commis.api.role.models import Role
class MultipleChoiceAnyField(forms.MultipleChoiceField):
"""A MultipleChoiceField with no validation."""
def valid_value(self, *args, **kwargs):
return True
class NodeForm(forms.ModelForm):
run_list = MultipleChoiceAnyField()
class Meta:
model = Node
fields = ('name',)
def __init__(self, *args, **kwargs):
super(NodeForm, self).__init__(*args, **kwargs)
def clean_run_list(self):
run_list = self.cleaned_data['run_list']
ret = []
for entry in run_list:
if '[' not in entry:
raise ValidationError('Unparseable run list entry "%s"' % entry)
entry_type, entry_name = entry.rstrip(']').split('[', 1)
entry_class = {'role': Role, 'recipe': CookbookRecipe}.get(entry_type)
if entry_class is None:
raise ValidationError('Unknown run list entry type "%s"' % entry_type)
if not entry_class.objects.filter(name=entry_name).exists():
raise ValidationError('Unknown %s "%s"' % (entry_class._meta.verbose_name, entry_name))
ret.append({'type': entry_type, 'name': entry_name})
return ret
def save(self, *args, **kwargs):
node = super(NodeForm, self).save(*args, **kwargs)
node.run_list.delete()
for entry in self.cleaned_data['run_list']:
node.run_list.create(**entry)
return node
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment