I have written this function in Django to override the 'label suffix and form field error message. Within the same function, the lebel suffix is working (the colon is removed) but the error message did not replaced by with customized one.
Here is the form class with the function:
class User_accountModelForm(forms.ModelForm):
# to remove colons from the labels:
def __init__(self, *args, **kwargs):
kwargs.setdefault('label_suffix', '')
super(User_accountModelForm, self).__init__(*args, **kwargs)
# changing error messages:
for field in self.fields.values():
field.error_messages = {'required':'The field {fieldname} is required'.format(fieldname=field.label)}
class Meta:
model = User_account
fields = ['first_name', 'other fields']
any help or clue is appreciated
To override the forms error messages, add it to the forms Meta; see also the ModelForm docs:
class User_accountModelForm(ModelForm):
class Meta:
model = User_account
fields = ['first_name', 'other fields']
error_messages = {
'first_name': {
# for example:
'max_length': _("This writer's name is too long."),
},
}
Related
Why isn't it possible to have a readonly inline related object in the django admin?
In the example below, as soon as I add id in the readonly_fields, it breaks when trying to save the OtherFoo model.
I found this ticket in the django project that was closed years ago and the alternate ticket does not help.
class FooInline(admin.TabularInline):
model = Foo
fields = (
"id",
"link",
"content",
)
readonly_fields = (
"id", # <===============
"link",
"content",
)
class OtherFooAdmin(admin.ModelAdmin):
inlines = [
FooInline,
]
If I'm remembering correctly, readonly fields don't actually post their values when the form is posted. What I've done to fix this is to make a custom admin form that has a custom clean method that sorta injects that value back into the form.
This is ripped from my own code:
class FooAdminForm(forms.ModelForm):
class Meta:
model = Foo
exclude = ['name']
def __init__(self, *args, **kwargs):
super(FooAdminForm, self).__init__(*args, **kwargs)
if kwargs.get('id') or 'id' in kwargs.get('initial'):
self.fields['id'].widget.attrs={'class': 'form-control', 'readonly': 'true'}
return self
def clean_id(self):
instance = getattr(self, 'instance', None)
if instance and instance.pk:
return instance.id
else:
return self.cleaned_data['id']
I want to change the name of the widget but then i have two names inside the input
class DocumentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
# to delete colon after field's name
kwargs.setdefault('label_suffix', '')
super(DocumentForm, self).__init__(*args, **kwargs)
class Meta:
model = Document
name = "document"
fields = ('id',
'comment',
'private',
'position',
'marked')
# fields = '__all__'
marked = forms.IntegerField(
required=False,
widget=forms.NumberInput(
attrs={
'name': "asdasdjasdasjdldsa",
'id': "device_documents___name___marked",
'class': 'check preview_image',
'onchange': 'cbChange(this)',
'mazen': "document_set-__name__-position"
},
)
)
but if i print this i have two name name="marked" and name="asdasdjasdasjdldsa" how to delete the first one?
print(f["marked"])
<input type="number" name="marked" name="asdasdjasdasjdldsa" id="device_documents___name___marked" class="check preview_image" onchange="cbChange(this)" mazen="document_set-__name__-position">
Django needs the name of the field to match the class definition. Otherwise it wouldn't be possible to process the submitted form data. Your only way of changing the widget's name attribute is to change the form field definition.
You didn't say why you want the name attribute to change. If you really wanted to hack it. You could create a custom widget with a template that uses the desired name.
I have used the code in django 1.6 but when trying it in django 1.8.6 I get:
AttributeError: 'SignupDataForm' object has no attribute 'fields'
at this line, but also generaly whenever asking for fields:
merged_field_order = list(self.fields.keys())
My SignupDataForm is a child declared like this:
class SignupDataForm(BaseUserDataForm):
reg_user_badge = forms.CharField(label="Give Points to a Friend",required=False,widget = TextInput(attrs={'placeholder': 'Username (optional)'}),validators=[validate_friendname])
class Meta(BaseUserDataForm.Meta):
model = UserData
fields = BaseUserDataForm.Meta.fields + ('terms_conditions',)
#terms_conditions is also a model field but not added to the parent definition
def __init__(self, *args, **kwargs):
super(SignupDataForm, self).__init__(*args, **kwargs)
self.fields['terms_conditions'].required = False
self.fields['gender'].widget = Select(choices=GENDER_CHOICES,attrs={'class':'signup_select',})
self.fields['password2'].widget.attrs['onblur'] ="check_pass()"
self.fields['password1'].widget.attrs['onblur'] ="check_pass()"
def clean(self):
#clean overwrite
What is weird is that if I use the parent form everything works fine, I get no error. Also if I place a print fields in the META declaration the tuple with fields is there. The shortend code for the parent is here:
class BaseUserDataForm(forms.ModelForm):
url = forms.CharField(max_length = 30, label="Don't type here (anti spam protection)",validators=[validate_name_honeypots])
class Meta:
model = UserData
fields = ('****model fields named without terms_conditions field****')
def __init__(self, *args, **kwargs):
super(BaseUserDataForm, self).__init__(*args, **kwargs)
The error occurs in another child:
class BaseSignupForm(SignupDataForm):
username = forms.CharField(label=_("Username"),
max_length=get_username_max_length(),
min_length=app_settings.USERNAME_MIN_LENGTH,
widget=forms.TextInput(
attrs={'placeholder':
_('Username'),
'autofocus': 'autofocus'}))
email = forms.EmailField(widget=forms.TextInput(
attrs={'type': 'email',
'placeholder': _('E-mail address')}))
def __init__(self, *args, **kwargs):
email_required = kwargs.pop('email_required',
app_settings.EMAIL_REQUIRED)
self.username_required = kwargs.pop('username_required',
app_settings.USERNAME_REQUIRED)
super(BaseSignupForm, self).__init__(*args, **kwargs)
# field order may contain additional fields from our base class,
# so take proper care when reordering...
field_order = ['email', 'username']
merged_field_order = list(self.fields.keys())
Does anybody know what am I doing wrong?
UPDATE - SOLVED:
Solved. Not an python ModelForm or allauth issue at all. There was a form below, partially wrapped and partially commented that I didn't see and it caused an intendention error that manifest it such a weird manner ....
I can see how to add an error message to a field when using forms, but what about model form?
This is my test model:
class Author(models.Model):
first_name = models.CharField(max_length=125)
last_name = models.CharField(max_length=125)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
My model form:
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
The error message on the fields: first_name and last_name is:
This field is required
How do I change that in a model form?
For simple cases, you can specify custom error messages
class AuthorForm(forms.ModelForm):
first_name = forms.CharField(error_messages={'required': 'Please let us know what to call you!'})
class Meta:
model = Author
New in Django 1.6:
ModelForm accepts several new Meta options.
Fields included in the localized_fields list will be localized (by setting localize on the form field).
The labels, help_texts and error_messages options may be used to customize the default fields, see Overriding the default fields for details.
From that:
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
labels = {
'name': _('Writer'),
}
help_texts = {
'name': _('Some useful help text.'),
}
error_messages = {
'name': {
'max_length': _("This writer's name is too long."),
},
}
Related: Django's ModelForm - where is the list of Meta options?
Another easy way of doing this is just override it in init.
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def __init__(self, *args, **kwargs):
super(AuthorForm, self).__init__(*args, **kwargs)
# add custom error messages
self.fields['name'].error_messages.update({
'required': 'Please let us know what to call you!',
})
I have wondered about this many times as well. That's why I finally wrote a small extension to the ModelForm class, which allows me to set arbitrary field attributes - including the error messages - via the Meta class. The code and explanation can be found here: http://blog.brendel.com/2012/01/django-modelforms-setting-any-field.html
You will be able to do things like this:
class AuthorForm(ExtendedMetaModelForm):
class Meta:
model = Author
field_args = {
"first_name" : {
"error_messages" : {
"required" : "Please let us know what to call you!"
}
}
}
I think that's what you are looking for, right?
the easyest way is to override the clean method:
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def clean(self):
if self.cleaned_data.get('name')=="":
raise forms.ValidationError('No name!')
return self.cleaned_data
I have a cleaner solution, based on jamesmfriedman's answer.
This solution is even more DRY, especially if you have lots of fields.
custom_errors = {
'required': 'Your custom error message'
}
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def __init__(self, *args, **kwargs):
super(AuthorForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].error_messages = custom_errors
You can easily check and put custom error message by overriding clean()method and using self.add_error(field, message):
def clean(self):
super(PromotionForm, self).clean()
error_message = ''
field = ''
# reusable check
if self.cleaned_data['reusable'] == 0:
error_message = 'reusable should not be zero'
field = 'reusable'
self.add_error(field, error_message)
raise ValidationError(error_message)
return self.cleaned_data
I can see how to add an error message to a field when using forms, but what about model form?
This is my test model:
class Author(models.Model):
first_name = models.CharField(max_length=125)
last_name = models.CharField(max_length=125)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
My model form:
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
The error message on the fields: first_name and last_name is:
This field is required
How do I change that in a model form?
For simple cases, you can specify custom error messages
class AuthorForm(forms.ModelForm):
first_name = forms.CharField(error_messages={'required': 'Please let us know what to call you!'})
class Meta:
model = Author
New in Django 1.6:
ModelForm accepts several new Meta options.
Fields included in the localized_fields list will be localized (by setting localize on the form field).
The labels, help_texts and error_messages options may be used to customize the default fields, see Overriding the default fields for details.
From that:
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = ('name', 'title', 'birth_date')
labels = {
'name': _('Writer'),
}
help_texts = {
'name': _('Some useful help text.'),
}
error_messages = {
'name': {
'max_length': _("This writer's name is too long."),
},
}
Related: Django's ModelForm - where is the list of Meta options?
Another easy way of doing this is just override it in init.
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def __init__(self, *args, **kwargs):
super(AuthorForm, self).__init__(*args, **kwargs)
# add custom error messages
self.fields['name'].error_messages.update({
'required': 'Please let us know what to call you!',
})
I have wondered about this many times as well. That's why I finally wrote a small extension to the ModelForm class, which allows me to set arbitrary field attributes - including the error messages - via the Meta class. The code and explanation can be found here: http://blog.brendel.com/2012/01/django-modelforms-setting-any-field.html
You will be able to do things like this:
class AuthorForm(ExtendedMetaModelForm):
class Meta:
model = Author
field_args = {
"first_name" : {
"error_messages" : {
"required" : "Please let us know what to call you!"
}
}
}
I think that's what you are looking for, right?
the easyest way is to override the clean method:
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def clean(self):
if self.cleaned_data.get('name')=="":
raise forms.ValidationError('No name!')
return self.cleaned_data
I have a cleaner solution, based on jamesmfriedman's answer.
This solution is even more DRY, especially if you have lots of fields.
custom_errors = {
'required': 'Your custom error message'
}
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
def __init__(self, *args, **kwargs):
super(AuthorForm, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].error_messages = custom_errors
You can easily check and put custom error message by overriding clean()method and using self.add_error(field, message):
def clean(self):
super(PromotionForm, self).clean()
error_message = ''
field = ''
# reusable check
if self.cleaned_data['reusable'] == 0:
error_message = 'reusable should not be zero'
field = 'reusable'
self.add_error(field, error_message)
raise ValidationError(error_message)
return self.cleaned_data