I need to somehow hook the Model's max_length constraints into a Form object.
Say I define a Model with a field: name = models.CharField(max_length=30)
Now I define a Form object with the same field: name = forms.CharField(max_length=30)
Question is, is there someway to synchronize the two? If I define a Model first, could I define the max_length of the Form class based on what I did with the Model class?
Using a ModelForm makes sense if you have a form related directly to a model.
Another way to pick up the max_length attribute from a model is to use the _meta attribute of the model like so:
>>> SomeModel._meta.get_field('some_field').max_length
64
>>>
so:
from models import *
class MyForm(forms.Form):
some_field = forms.CharField(label='Some Field',
max_length=SomeModel._meta.get_field('some_field').max_length)
CharField docs
Use ModelForms:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelform
This way the forms inherit directly from the models and you do not have to repeat yourself.
Related
Could anyone explain to me similarities and differences of Django's forms.Form & forms.ModelForm?
Forms created from forms.Form are manually configured by you. You're better off using these for forms that do not directly interact with models. For example a contact form, or a newsletter subscription form, where you might not necessarily be interacting with the database.
Where as a form created from forms.ModelForm will be automatically created and then can later be tweaked by you. The best examples really are from the superb documentation provided on the Django website.
forms.Form:
Documentation: Form objects
Example of a normal form created with forms.Form:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
forms.ModelForm:
Documentation: Creating forms from models
Straight from the docs:
If your form is going to be used to
directly add or edit a Django model,
you can use a ModelForm to avoid
duplicating your model description.
Example of a model form created with forms.Modelform:
from django.forms import ModelForm
from . import models
# Create the form class.
class ArticleForm(ModelForm):
class Meta:
model = models.Article
This form automatically has all the same field types as the Article model it was created from.
The similarities are that they both generate sets of form inputs using widgets, and both validate data sent by the browser. The differences are that ModelForm gets its field definition from a specified model class, and also has methods that deal with saving of the underlying model to the database.
Here's how I'm extending the builtin UserCreationForm myapp/forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
class RegisterForm(UserCreationForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
email = forms.CharField(max_length=75)
class Meta(UserCreationForm.Meta):
fields = ('username','first_name','last_name', 'email')
The difference is simple, ModelForm serves to create the form of a Model.
meaning that Model is designed to create kind of schema of your table where you will save data from form submission and ModelForm simply creates a form of the model (from the schema of the table)
# This creates a form from model Article
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content', 'reporter']
Form is a common form that is unrelated to your database (model ).
# A simple form to display Subject and Message field
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
To say in other words,
If you have a model in your app and you want to create a Form to enter data in that model (and by it to a db) use forms.ModelForm
If you simple want to create a form using django use form.Form
But you can also use this together:
from django import forms
# A simple form to display Subject and Message field
class ContactForm(forms.ModelForm):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
class Meta:
model = Contact #when you have this model
fields = [
'subject',
'message',
]
I am working through how to use Django's forms (https://docs.djangoproject.com/en/1.11/topics/forms/#more-on-fields) and I can't see a way to generate a form structure that is based on a defined Model. In Symfony, I remember I was able to get my form to automatically include all parameters of myModel (for example) even if any new attributes were later added to the model.
For example:
class myModel(models.Model):
name = models.CharField(max_length=50)
created=models.DateTimeField(null=False)
modified=models.DateTimeField(null=True)
myParameter= models.IntegerField(default=None)
// ... plus many more parameters
Rather than having to manually type corresponding rows into my class myModelForm(forms.Form):, I'm looking/hoping for a 'catch all'.
from django.forms import ModelForm
class myModelForm(ModelForm):
class Meta:
model = myModel
fields = '__all__'
More details selecting-the-fields-to-use
I have a model with a foreignkey to another model
class Person(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Organisation(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
contact = models.ForeignKey(Person)
I want to use a CreateView to be able to create a new Organisation, but be able to enter a new contact person details on the same page (i.e. when a new organisation is created, a new contact person must also be created).
What is the nicest (DRY) way to do this?
In the CreateView use the model that has the ForeignKey and since it inherits the FormMixin's form_class use the modelform_factory for that model with extra fields the fields of ForeignKey's model. Finally, overload either the validation or save methods with a get_or_create with the ForeignKey's model fields, passing the result to the ModelForm.
An alternative approach would be to chain two CreateViews. First with the Organization as the model, using the Contact's CreateView URL as its success_url. You can even use js to replace the first submit with the html of the second view.
Or you can try some hacks floating around utilizing formsets, though I prefer the first two methods in your case. The formset hacks are better suited for many-to-many relationships.
I'm only using forms.Form but I'm trying to show two choice fields that have selections of the associated models.
It basically needs to show the same names but in both fields. Here's what I'm using.
class ManagersForm(forms.Form):
class Meta:
model = A
leader = forms.ChoiceField()
co-leader = forms.ChoiceField()
Is there not just a way that I can parse the users?
users = MyUser.objects.filter(a=i)
You need to use a ModelForm not Form, if the field from the Model is a ForeignKey the form will render the field as a dropdown of the associated model:
class ManagersForm(forms.ModelForm):
class Meta:
model = A
Is there a simple way to replace a form field in Django with another form? Specifically, I have a one-to-one relationship between two models, and it would be great if I could define a field to actually be defined as another form, something like this:
class FirstModelForm(forms.ModelForm):
class Meta:
model = FirstModel
class SecondModelForm(forms.ModelForm):
second = forms.InnerForm(form=FirstModelForm)
class Meta:
model = SecondModel
Any ideas? Or should I write it myself and submit to Django codebase? ;-)