I'm implementing a Django Form witch should contain the field 'fieldA' from modelA
:
class ModelA(models.Model):
fieldA = models.CharField(max_length=8)
...
My question is: Is there a way to have Django form, which will automatically handle validation of fieldA (check the max_length)? I know I Could use form.ModelForm
class referring to ModelA, but then the form would reflect all the fields of the ModelA. I would like to use simple forms.Form
.
I'm looking for a solution like:
class formX(forms.Form):
fieldA = forms.CharField(**modelA.fieldA.constraints)
fieldB = ... some other fields not related to ModelA ...
.... even more fields
CodePudding user response:
Maybe this question is an XY problem, but let me try...
Direct question: get field constraints from existing model
from django import forms
from django.db import models
class Foo(models.Model):
x = models.CharField(max_length=30)
y = models.IntegerField(null=True)
class FooForm(forms.Form):
foo_x = forms.CharField(max_length=Foo._meta.get_field('x').max_length)
You can access the field directly in two ways:
ModelClass.field_name.field
(kind of hack,ModelClass.field_name
is adjango.db.models.query_utils.DeferredAttribute
)ModelClass._meta.get_field('field_name')
(better way, described somewhere in docs)
However, this way you have to a) update form if field constraints are added or b) specify all attributes in advance (max_length
, min_length
, verbose_name
, blank
, etc.), making declaration of FooForm.foo_x
too verbose.
Alternatives
Fields subset
First of all, if you need a subset of Foo
fields, use ModelForm
and specify them:
class FooForm(forms.ModelForm):
class Meta:
fields = ('x',)
Now you have a form with only x
field.
Add some fields
If you want to add fields to this form (that are not related to other model), do it:
class FooForm(forms.ModelForm):
another_field = forms.IntegerField()
class Meta:
fields = ('x',)
def clean_another_field(self):
data = self.cleaned_data['another_field']
if data != 42:
raise ValidationError('Not an answer!') # i18n should be here
return data
Also you can override clean
and save
methods for another goals, documentation explains that nicely.
Mix fields from different models
If you need fields of two different models to be present in one form, you don't. You need two separate forms in this case, plus some inter-validation logic outside of this forms maybe (as a view method, for example, or as another class that is not a form). Maybe what you need is inline formset, it doesn't represent two mixed forms, but at least has some inter-model communication.