Django manytomany field is absent in modelform - django

Suppose I have following Model
class Member(models.Model):
name = ...
qualities = models.ManyToManyField(ProfessionalQuality, related_name='members')
And following form:
class CommonMemberForm(forms.ModelForm):
"""This form for gathering common features in both admin and member forms
"""
class Meta:
model = Member
fields = '__all__'
def __init__(self, *args, **kwargs):
super(CommonMemberForm, self).__init__(*args, **kwargs)
self.fields['qualities'].validators.append(...)
When I try to instantiate form, I get KeyError: 'qualities' are not in self.fields. Why is that?
This code works in admin.
What is the correct way of handling such fields?

Try this:
class CommonMemberForm(forms.ModelForm):
"""This form for gathering common features in both admin and member forms
"""
class Meta:
model = Member
fields = '__all__'
widgets = {
'qualities': forms.CheckboxSelectMultiple()
}
def __init__(self, *args, **kwargs):
super(CommonMemberForm, self).__init__(*args, **kwargs)
#self.fields['qualities'].widget...

This works for me:
class CommonMemberForm(AbstractUser):
class Meta:
model = Member
fields = '__all__'
def __init__(self, *args, **kwargs):
super(RegularUser, self).__init__(*args, **kwargs)
self._meta.get_field('qualities').validators = [validate_qualities]

Related

Django 1.11 pass kwarg to modelform field

I would like to pass a kwarg to set a modelform field but im struggling to figure out how to do it.
My URL is as follows:
url(r'^tent/create/(?P<munc>\d+)',views.TentCreate.as_view(),name='tent_create'),
My view is simply:
class TentCreate(CreateView):
model = Tent
form_class = TentForm
And my form:
class TentForm(ModelForm):
class Meta:
model = Tent
exclude =('asfo','niho')
def __init__(self, *args, **kwargs):
super(TentForm, self).__init__(*args, **kwargs)
self.fields['primary'].queryset = Mark.objects.filter(munc=self.kwargs['munc'])
from the model:
class Tent(models.Model):
primary = models.ForeignKey(Mark,on_delete=models.CASCADE)
I can render the form fine without overriding def __init, with no filtering applied to the 'primary' field.
However attempting to use the def __init code I've described above to pass the munc kwarg to the form field is resulting in the following error:
"'TentForm' object has no attribute 'kwargs'"
I've been going around in circles trying to work through this so I would be really appreciative if anyone is able to provide me some guidance to solve this. This is my first Django project so I'm learning how I go so I assume I have made some fundamental error somewhere here!
Try overriding get_form_kwargs method:
views.py
class TentCreate(CreateView):
model = Tent
form_class = TentForm
def get_form_kwargs(self):
kwargs = super(TentCreate, self).get_form_kwargs()
kwargs.update({'munc': self.kwargs['munc']})
return kwargs
forms.py
class TentForm(ModelForm):
class Meta:
model = Tent
exclude =('asfo','niho')
def __init__(self, *args, **kwargs):
munc = kwargs.pop('munc')
super(TentForm, self).__init__(*args, **kwargs)
self.fields['primary'].queryset = Mark.objects.filter(munc=munc)
class TentCreate(CreateView):
form_class = TentForm
def get_form(self, form_class=None):
if form_class is None:
form_class = self.get_form_class()
kwargs = self.get_form_kwargs()
print(kwargs, self.kwargs)
kwargs.update(self.kwargs)
return form_class(**kwargs)
forms.py
class TentForm(ModelForm):
class Meta:
model = Tent
exclude =('asfo','niho')
def __init__(self, *args, **kwargs):
munc=self.kwargs['munc']
super(TentForm, self).__init__(*args, **kwargs)
self.fields['primary'].queryset = Mark.objects.filter(munc=munc)
you must pop munc before call super(TentForm, self).__init__(*args, **kwargs)

Add class on modelform django

How to dynamically add a class to a field on a modelForm.
class MyForm(ModelForm):
class Meta:
model = Post
fields = ['type']
widgets = {
'type' : RadioSelect()
}
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['type'].widget.attrs.update( {'class':'radio-inline'})
I did the code above but it is not working for some reason. The class 'radio-inline' is not created on the template.

How do I add a help_text to a ModelForm?

I know how to add a 'class' or other widget attribute to an automatically built ModelForm:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
How do I insert a help_text= into the example_field Field?
As of Django 1.6: You can edit it within the Meta class. Try:
class ExampleSettingForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ExampleSettingForm, self).__init__(*args, **kwargs)
self.fields['example_field'].widget.attrs['class'] = 'css_class'
class Meta:
model = Example
help_texts = {
'example_field': ('Here is some help'),
}
Docs on this are at https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#overriding-the-default-fields. See release notes at http://django.readthedocs.org/en/latest/releases/1.6.html . You can set your own label, help_text and error_messages.
This is what I did in Django 1.9:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('__all__')
help_texts = {
"my_field": "This is case sensitive..."
}

Django different forms for admin model

Is there any way to load different admin forms for editing an objects depending of what object is needed to be updated?
For example - we have an MPTTModelAdmin objects. And for root objects we don't want to see some fields:
class RootObjectForm(ModelForm):
class Meta:
model = Author
exclude = ('title',)
class ChildObjectForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'birth_date')
But I don't know how to get object fields in forms.py or admin.py.
You can always supply your own form class for a ModelAdmin class: https://docs.djangoproject.com/en/1.5/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
From there you can access fields by key, just like any other Django form:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModeForm, self).__init__(*args, **kwargs)
# access whatever field by key
# self.fields['field-name']
In forms.py file you can get object fields and their value at two stages.
1 : when form is submitted.
clean method does initial validations.
def clean(self):
""" validation of address form """
cleaned_data = super(WebsiteAddressForm, self).clean()
field1_value = self.cleaned_data.get("field1")
print field1_value
return cleaned_data
2 : when form is initialized. ____init____ method will call.
class MyForm(forms.ModelForm):
class Meta:
model = Model1
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
#self.fields['field1']

Overriding max_value in django form

I use a ModelForm and I want to set a max_value for an IntegerField without losing the other attributes which where created from the model (verbose_name, etc.).
This is my ModelForm:
class DataForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DataForm, self).__init__(*args, **kwargs)
self.fields['start_range_points'].max_value = 1000
class Meta():
model = DataModel
This doesn't work, django does not apply the validation for large numbers. If I create the field in the following way the validation works but I lose the information which was created from the Model.
class DataForm(ModelForm):
start_range_points = forms.IntegerField(min_value=0, max_value=1000)
class Meta():
model = DataModel
What can I do to achieve something similar to attempt #1?
The validator for max_value is added in IntegerField's __init__ function if max_value is present. So you will need to manually add the validator, something like:
from django.core.validators import MaxValueValidator
class DataForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DataForm, self).__init__(*args, **kwargs)
validators = [ v for v in self.fields['start_range_points'].validators if not isinstance(v, MaxValueValidator) ]
validators.append( MaxValueValidator(1000) )
self.fields['start_range_points'].validators = validators
class Meta():
model = DataModel