I'm building a formset like so:
InterestFormSet = modelformset_factory(Interest, \
formset=BaseInterestFormSet, exclude=('userid',), extra=2)
And I want set default labels and values for elements of this form.
I know that in simple forms I can use the fields dict to change these things for specific fields of the form, but how is this done with a formset?
I tried extending the formset (as you can see) to see if I could access self.fields from within __init__, but no luck.
Something like this should do what you want:
class InterestForm(ModelForm):
pub_date = DateField(label='Publication date')
class Meta:
model = Interest
exclude = ('userid',)
InterestFormSet = modelformset_factory(Interest, form=InterestForm, extra=2)
Formsets don't have fields, they only have forms which have fields. So you have to deal directly with those forms.
Related
So, I have a ModelAdmin that I need to add extra fields to. These fields do not exist on the model, but will be dynamically added to a custom ModelForm through the init method, and logic inside clean will handle the returned data on save.
I can't seem to find any solid information related to adding custom non-model fields to a ModelAdmin form. The closest I have come is by overriding get_fields on the ModelAdmin class and updating self.form.declared_fields with the new fields I'd like to add.
This just doesn't feel very clean to me and I was curious if there was a better way to add new fields to a ModelAdmin dynamically?
You can also use this way to add fields not in the models.py
in admin.py:::
from django.utils.translation import gettext as _
class TrialAdmin(admin.ModelAdmin):
fields = (..., 'non_model_field',...,)
def non_model_field(self, instance):
# this method name should be same as new field name defied above in fields.
# [what u need to do here]
non_model_field.short_description = _("non_model_field")
#This value 'short_description' defines what the field name is shown as in admin similar to 'verbose_name' in models.
admin.site.register(..., TrialAdmin)
from django import forms
from .models import NewsSignUp
class NewsSignUpForm(forms.ModelForm):
class Meta:
model = NewsSignUp
fields = ['email', 'first_name']
here
This code works perfectly fine. But, when I remove "class Meta:" as below, it throws a ValueError saying "ModelForm has no model class specified."
from django import forms
from .models import NewsSignUp
class NewsSignUpForm(forms.ModelForm):
model = NewsSignUp
fields = ['email', 'first_name']
Can someone please give an explanation? :(
You are creating a ModelForm subclass. A model form has to have a model to work from, and the Meta object configures this.
Configuration like this is grouped into the Meta class to avoid name clashes; that way you can have a model field in your form without that interfering with the configuration. In other words, by using class Meta: you get a nested namespace used just to configure the ModelForm in relation to the model.
The namespace for the ModelForm class body itself then (outside Meta) is reserved for the form fields themselves, as well as form methods. You'd normally just let ModelForm generate those fields from your model, but you can, in principle, add fields to this. Another reason to put fields in the class is to completely replace any of the generated fields with your own version.
From the Model Forms documentation:
ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.
Fields defined declaratively are left as-is, therefore any customizations made to Meta attributes such as widgets, labels, help_texts, or error_messages are ignored; these only apply to fields that are generated automatically.
Because ModelForm expects the configuration to be set under the Meta name, you can't just remove that and put model and fields in the ModelForm class itself; that's just the wrong place.
I'm trying to set up a django form consisting solely of a formset. In forms.py I have:
class StudentEnrolmentForm(forms.ModelForm):
school_class = forms.ModelChoiceField(SchoolClass.objects.currently_enrolling())
class Meta:
model = StudentApplication
fields = []
StudentEnrolmentFormSet = modelformset_factory(StudentApplication, StudentEnrolmentForm, extra=0)
but I'm unclear how to incorporate the FormSet into a CBV (In this case I've chosen a FormView). In this case I'm basically displaying a table of students, and allowing the operator to assign each student to a class. I only want a single 'submit' button at the end of the page.
If you will take a look on sources of Django views and check how FormView is working, you find that it just overrides default get and post methods of base View class and adds some additional methods for the form handling.
So you can:
try to assign your formset to the form_class field of your view and
play around. Probably you will have to override some additional
methods;
take a look on https://github.com/AndrewIngram/django-extra-views;
if options #1 and #2 causes too much pain - use default View
I have one model that has a ManyToMany Field (let's call it "Options") with another Model
When I create the ModelForm it displays all options.
Is there any way to exclude some option values or to show only some of them?
Here is an example:
models.py
class Options (model.Models):
name = ...
...
class Anything (model.Models):
...
options = ManyToManyField(Options)
values of "Options" in my DB:
["OK",
"OK_2",
"NOT_OK",
"OK_3,
"NOT_OK_2"]
Let's say that I need to show ONLY the "OK" values and hide or not to show the "NOT_OK" values.
Is there any way to do this with ModelForms?
You certainly can filter the queryset for a foreign key field or m2m on the related model by using a Form or more commonly a ModelForm.
The reason doing this at form level is useful is because that filtering could well be based on business logic which is not applicable in all cases and so allows more flexibility than defining it against the model for example.
While you can do this while defining the form fields it is best to do it once the form has been constructed and so it takes place at runtime and not compile time (I have just experienced a few interesting occasions where this has caused me some issues, however that was an earlier version of Django!)
The following ModelForm would do the job:
class AnythingForm(ModelForm):
options = forms.MultipleChoiceField()
def __init__(self, **kwargs):
super(AnythingForm, self).__init__(self, **kwargs)
self.fields['options'].queryset = Option.objects.filter({pass in your filters here...})
class Meta:
model = Anything
You can pass the limit_choices_to parameter to your ManyToMany field:
from django.db.models import Q
class Anything (models.Model):
options = models.ManyToManyField(Options,
limit_choices_to=Q(name__startswith='OK'))
In django 1.7 you can even pass a callable in case if list of choices should be changed dynamically.
I have a form in Django called PersonForm this forms model has a one-to-many relationship with Car. When displaying the PersonForm just like in the Django Admin I would like to allow my users to select/deselect from a list of Cars etc. Is this possible? I'm looking for information on where to start.
This is what I have so far for the PersonForm:
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ('description',)
The Models:
class Person(models.Model):
description = models.CharField(max_length="150")
class Car(models.Model):
make = models.CharField(max_length="25")
owner = models.ForeignKey('Person', related_name="Car")
So in the person form I need to show a list of cars that person is the owner of an allow selecting/deselecting of them. I'm assuming I can do this in the form i.e. using something like the related name.
Sounds like you want an inline model form. This give you the ability to add/remove Car objects from a Person within the Person form.
That previous link was for inlinemodeladmin. This next link is for an inline form:
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelforms-factory
I didn't have any chance with inline formset, so i would suggest to override your save method of the model, i feel it's more DRY:
class PersonForm(forms.ModelForm):
# add a field to select a car
car = forms.ModelChoiceField(car.objects.all())
class Meta:
model = Person
fields = ('description', 'car')
def save(self, commit=True):
instance = super().save(commit)
# set Car reverse foreign key from the Person model
instance.car_set.add(self.cleaned_data['car']))
return instance
I know this is an old thread, but since I found myself almost exclusively pointed here by google when searching, I thought I would include the following for anyone else looking for an answer.
The answer, I think, is to use
https://docs.djangoproject.com/en/3.1/ref/forms/fields/#modelchoicefield
or
https://docs.djangoproject.com/en/3.1/ref/forms/fields/#modelmultiplechoicefield
There is a good article on how to use the modelmultiplechoicefield at :
https://medium.com/swlh/django-forms-for-many-to-many-fields-d977dec4b024
But it works for one to many fields as well. These allow us to generate a form with multiple choices as checkboxes or similar widgets based upon a related field in a model.