How do I add a help_text to a ModelForm? - django

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..."
}

Related

How to delete label of a form in Django

How can I delete label of form in Django. I have something like this.
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['user_image']
widgets = {
'user_image': forms.FileInput(attrs={'class': 'image-upload', 'label': ''}),
}
image-upload class does not include label. I have a auto-generated label and is written 'user-image'
You can remove it via init:
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['user_image']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['user_image'].label = ''

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.

Limit the Choices shown from ManyToMany ForeignKey

How do I limit the values returned via the ManyToMany relationship and thus displayed in the <SELECT> field on my form to only show the spots which were created by the currently logged in user?
models.py
class Project(models.Model):
owner = models.ForeignKey(User, editable=False)
...
spots = models.ManyToManyField(to='Spot', blank=True, )
class Spot(models.Model):
owner = models.ForeignKey(User, editable=False)
spot_name = models.CharField(max_length=80, blank=False)
forms.py
from django import forms
from .models import Project, Spot
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
exclude = ('owner', )
class SpotForm(forms.ModelForm):
class Meta:
model = Spot
exclude = ('owner', )
I'm using GenericViews for Update and Create and currently see all of the entries everyone has made into Spots when I'm updating or creating a Project. I want to see only the entries entered by the logged in user. For completeness sake, yes, the project.owner and spot.owner were set to User when they were created.
I've tried def INIT in the forms.py and using limit_choices_to on the manytomany field in the model. Either I did those both wrong or that's not the right way to do it.
thank you!
in your forms.py
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
exclude = ('owner', )
def __init__(self, user_id, *args, **kwargs):
self.fields['spots'] = forms.ModelChoiceField(widget=forms.Select, queryset=Project.objects.filter(owner=user_id))
class SpotForm(forms.ModelForm):
class Meta:
model = Spot
exclude = ('owner', )
def __init__(self, user_id, *args, **kwargs):
self.fields['spot_name'] = forms.ModelChoiceField(widget=forms.Select, queryset=Spot.objects.filter(owner=user_id))
in your views.py
user_id = Project.objects.get(owner=request.user).owner
project_form = ProjectForm(user_id)
spot_form = SpotForm(user_id)
As I mentioned above, Dean's answer was really close, but didn't work for me. Primarily because request is not accessible in the view directly. Maybe it is in older Django versions? I'm on 1.9. Thank you Dean, you got me over the hump!
The gist of what's going on is adding User into the kwargs in the View, passing that to the ModelForm, remove User from the kwargs and use it to filter the Spots before the form is shown.
This is the code that worked for my project:
views.py
class ProjectUpdate(UpdateView):
model = Project
success_url = reverse_lazy('projects-mine')
form_class = ProjectForm
def dispatch(self, *args, **kwargs):
return super(ProjectUpdate, self).dispatch(*args, **kwargs)
def get_form_kwargs(self):
kwargs = super(ProjectUpdate, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
forms.py
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
exclude = ('owner', 'whispir_id')
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user')
super(ProjectForm, self).__init__(*args, **kwargs)
self.fields['spots'] = forms.ModelMultipleChoiceField(queryset=Spot.objects.filter(owner=user_id))
class SpotForm(forms.ModelForm):
class Meta:
model = Spot
exclude = ('owner', )
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user')
super(SpotForm, self).__init__(*args, **kwargs)
self.fields['spot_name'] = forms.ModelMultipleChoiceField(queryset=Spot.objects.filter(owner=user_id))

Django manytomany field is absent in modelform

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]

Dynamic Form fields in `__init__` in Django admin

I want to be able to add fields to django admin form at runtime. My model and form:
#admin.py
class SitesForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SitesForm, self).__init__(*args, **kwargs)
self.fields['mynewfield'] = forms.CharField()
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites,SitesAdmin)
#model.py
class Sites(models.Model):
url = models.URLField(u'URL')
is_active = models.BooleanField(default=True, blank=True)
is_new = models.BooleanField(default=False, blank=True)
group = models.ForeignKey('SitesGroup')
config = models.TextField(blank=True)
Field mynewfield isn't displayed in form. Why?
You shouldn't be adding a new field to your form in that way, you can just do it as you would any other field and the form will contain both the Model's original fields and your new fields:
class SitesForm(forms.ModelForm):
mynewfield = forms.CharField(max_length=255, blank=True)
class Meta:
model = Sites
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites, SitesAdmin)
Edit: Sorry, should have read what you had written a little better. If you want a dynamic field like that, then you need to do the following and it will do exactly what you want:
class SitesForm(forms.ModelForm):
class Meta:
model = Sites
def __init__(self, *args, **kwargs):
self.base_fields['mynewfield'] = forms.CharField(max_length=255, blank=True)
super(SitesForm, self).__init__(*args, **kwargs)
class SitesAdmin(admin.ModelAdmin):
form = SitesForm
admin.site.register(Sites, SitesAdmin)
It's the base_fields that gets composed by the metaclass that holds the fields that the form will use.
Solution:
class AdminForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(AdminForm, self).__init__(*args, **kwargs)
self.fields.insert(1, 'myfield', forms.CharField())
class MyAdmin(admin.ModelAdmin):
form = AdminForm
def get_fieldsets(self, request, obj=None):
return (
(None, {
'fields': (..., 'myfield',),
}),
)