Created
November 27, 2014 00:10
-
-
Save foxx/1968fe19f759e608452a to your computer and use it in GitHub Desktop.
Django partial forms mixin (alpha as fuck)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FormFieldQuerySetMixin(object): | |
""" | |
Adds support for changing RelatedField queryset | |
easily without having to patch __init__. | |
def get_FIELDNAME_queryset(self): | |
pass | |
""" | |
def __init__(self, *args, **kwargs): | |
super(FormFieldQuerySetMixin, self).__init__(*args, **kwargs) | |
assert isinstance(self, (ModelForm, )) | |
for field in self.fields.keys(): | |
fn = "get_%s_queryset" % ( field, ) | |
func = getattr(self, fn, None) | |
if func: | |
qs = func() | |
old_qs = self.fields[field].queryset | |
assert qs.model == old_qs.model | |
self.fields[field].queryset = qs | |
class CreateOnlyFormFieldMixin(object): | |
""" | |
Adds create-only field support into a model form, this | |
allows a field to be written at creation but not updated | |
""" | |
def __init__(self, *args, **kwargs): | |
super(CreateOnlyFormFieldMixin, self).__init__(*args, **kwargs) | |
for field_name in self.get_fields_createonly(): | |
assert field_name in self.fields, "invalid create-only field '%s'" % ( field_name, ) | |
if self.instance and self.instance.pk: | |
setattr(self.fields[field_name], '_createonly', True) | |
self.fields[field_name].widget.attrs['readonly'] = True | |
def _clean_fields(self): | |
for name, field in self.fields.items(): | |
is_createonly = getattr(field, '_createonly', False) | |
if field in self.data and is_createonly: | |
self.add_error(field, "Field is create-only") | |
return | |
super(CreateOnlyFormFieldMixin, self)._clean_fields() | |
@classmethod | |
def get_fields_createonly(self): | |
fields_createonly = getattr(self.Meta, 'fields_createonly', None) | |
fields_createonly = fields_createonly if fields_createonly else [] | |
return fields_createonly | |
class ReadOnlyFormFieldMixin(object): | |
""" | |
Adds read-only field support into form, allows fields to be | |
added dynamically, with inspiration from; | |
http://stackoverflow.com/questions/324477 | |
http://stackoverflow.com/questions/972 | |
""" | |
def __init__(self, *args, **kwargs): | |
super(ReadOnlyFormFieldMixin, self).__init__(*args, **kwargs) | |
for field_name in self.get_fields_readonly(): | |
assert field_name in self.fields, "invalid read-only field '%s'" % ( field_name, ) | |
setattr(self.fields[field_name], '_readonly', True) | |
self.fields[field_name].widget.attrs['readonly'] = True | |
self.fields[field_name].editable = False | |
def _clean_fields(self): | |
for name, field in self.fields.items(): | |
is_readonly = getattr(field, '_readonly', False) | |
if field in self.data and is_readonly: | |
self.add_error(field, "Field is read-only") | |
return | |
super(ReadOnlyFormFieldMixin, self)._clean_fields() | |
@classmethod | |
def get_fields_readonly(self): | |
fields_readonly = getattr(self.Meta, 'fields_readonly', None) | |
fields_readonly = fields_readonly if fields_readonly else [] | |
return fields_readonly | |
class WriteOnlyFormFieldMixin(object): | |
""" | |
Adds support for hiding instance value if field | |
is write only | |
""" | |
def __init__(self, *args, **kwargs): | |
super(WriteOnlyFormFieldMixin, self).__init__(*args, **kwargs) | |
for field_name in self.get_fields_writeonly(): | |
assert field_name in self.fields, "invalid write-only field '%s'" % ( field_name, ) | |
setattr(self.fields[field_name], '_writeonly', True) | |
if field_name in self.initial: | |
del self.initial[field_name] | |
@classmethod | |
def get_fields_writeonly(self): | |
fields_writeonly = getattr(self.Meta, 'fields_writeonly', None) | |
fields_writeonly = fields_writeonly if fields_writeonly else [] | |
return fields_writeonly | |
class PartialFormMixin(object): | |
""" | |
Adds partial form support which makes all fields optional | |
if form is created with partial attribute; | |
form = MyForm(data, partial=True) | |
""" | |
partial = False | |
def __init__(self, *args, **kwargs): | |
if 'partial' in kwargs: | |
self.partial = kwargs['partial'] | |
del kwargs['partial'] | |
super(PartialFormMixin, self).__init__(*args, **kwargs) | |
if self.partial: | |
for field in self.fields: | |
self.fields[field].required = False | |
def _post_clean(self): | |
if self.partial: | |
cleaned_data = dict([ (k,v) for (k,v) in self.cleaned_data.items() | |
if k in self.data ]) | |
self.cleaned_data = cleaned_data | |
super(PartialFormMixin, self)._post_clean() |
@collinanderson Doh, github didn't tell me that I had unread comments, just stumbled across this now. You might be right, I'll give it a try and update if it works, thanks :)
@collinanderson ...works a treat
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, You could probably simplify PartialFormMixin to something like this: