I am adding an extra field to a Django ModelForm like that:
class form(forms.ModelForm):
extra_field = forms.CharField(label='Name of Institution')
class Meta:
model = db_institutionInstitution
fields = ['conn_kind','time','inst_name2']
The form is actually working fine, but I cant prepopulate it. I use it in a modelformset_factory:
formset = modelformset_factory(db_institutionInstitution,form=form)
I manually run through a queryset and add the entry in the dictionary needed for the additional form in the formset. However, when I call:
formset1 = formset(prefix='brch',queryset=qs1)
the extra_field is not prepopulated as intended (the rest is working fine).
Can anyone help?
If you want to set a default.
extra_field = forms.CharField(label='Name of Institution', initial="harvard")
If you want to dynamically set a value put it on form initialization:
def __init__(self, *args, **kwargs):
super(form, self).__init__(*args, **kwargs)
self.fields['extra_field'].initial = "harvard"
Related
I have a modelform which generates a series of checkboxes to add children to a parent part. I have created a validator that checks for cyclic relationships. I'm currently getting errors however because "proposed_child" is a queryset containing however many values the user has selected. How do I have this validator run on each object in that queryset?
def __init__(self, qs, part, *args, **kwargs):
super(AddPartToAssemblyForm, self).__init__(*args, **kwargs)
self.part = part
self.fields['children'] = forms.ModelMultipleChoiceField(
queryset=qs,
widget=forms.CheckboxSelectMultiple
)
def clean_children(self):
proposed_child = self.cleaned_data['children']
part = self.part
validate_acyclic_relationship(part, proposed_child)
class Meta:
model = Part
fields = ['children']
I figured it out, I changed proposed_child to proposed children and changed my validator so that it iterates through the queryset it receives and validates each object in turn.
Now I have working validator but if the data is valid the form isn't returning anything in form.cleaned_data['children']
--edit--
needed to return proposed_children at the end of clean_children
I want to overwrite the __str__ method in Django admin when using the autocomplete_fields = () but the returned values are using __str__.
I have a form something like
class MyAdminForm(forms.ModelForm):
placement = forms.Select(
choices = Organisation.objects.active(),
)
class Meta:
model = Lead
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['placement'].label_from_instance = lambda obj: f'{str(obj)} {obj.post_code}'
This will provide back a Select with the organisation name and post code in the dropdown fields. But there are some 80k choices so I need to using autocomplete. Within within admin.py I have
class LeadAdmin(admin.ModelAdmin):
form = LeadAdminForm
autocomplete_fields = ('placement',)
As soon as I add the autocomplete_fields I lose my postcode and it reverts to just showing the __str__
Hoa can I used autocomplete_fields and overwrite the __str__ method?
This question is answered through Benbb96 comment above which I've copied here so I can close it
So maybe this answer can help you :
stackoverflow.com/a/56865950/8439435 – Benbb96
I'm trying to find best approach for what i want. And i could use some help for that.
I have Model A and Model B. Model B has
modela = forms.ForeignKey(Model a)
I want to create a view where you can edit both single Model A and several Model B's on same page. Django has formsets for this and they work great.
I have one detail though, that messes things up tiny bit. Namely - i want the widgets or model B fields to be different based on what choices they have done in previous fields of same object. Because - based on type, the widget has to be datetime picker input or plain textinput.
Model B looks like this:
class ModelB(models.Model):
m0odela = models.ForeignKey(ModelA)
target_value = models.CharField()
target_type = models.CharField( choices = ( there are choices))
target_threshold = models.CharField()
I know i can provide my own form for formset and i could do this widget assignment in that form.
But the problem is, that when formset has no instances/queryset then i cant check if 'target_type' has been set for forms instance. So i would have to do it based on self.data or self.initial in form. But self.initial is also not present in form.__init__(). What i can work with is self.data - but that is raw request.POST or request.GET data - which contains all keys like 'mymodelb_set-0-target_type'.
So i'm bit lost here. Do i have to do some key parsing and figure out which -target_type belongs to current form and get chosen value there and assign widgets based on this value?
Or do i have to create my own subclass of BaseInlineFormSet and override _construc_form there somehow? So that form would have initial key with related data in **kwargs.
Has someone ran into this kind of problem before?
Alan
Well i had to solve it so i solved it as good/bad i could.
I created my own subclass of inline formset:
class MyInlineFormSet(BaseInlineFormSet):
def _construct_form(self, i, **kwargs):
initial = {}
fname = '%s-%s-%s' % (self.prefix, i, 'important_field_name')
initial['target_type'] = self.data[fname] if fname in self.data.keys() else 'km'
kwargs.update({'initial':initial})
form = super(MyInlineFormSet, self)._construct_form(i, **kwargs)
return form
And then in the form class:
class MyNiftyForm(forms.ModelForm):
class Meta:
model = MyAwesomeObject
fields=('field_one', 'field_two', 'field_three')
def __init__(self, *args, **kwargs):
super(ServiceTargetForm, self).__init__(*args, **kwargs)
if self.instance:
if self.instance.field_one == 'date':
self.fields['field_one'].widget.attrs['class'] = 'datepicker'
if self.initial:
if self.initial['field_one'] == 'date':
self.fields['field_one'].widget.attrs['class'] = 'datepicker'
and then in view:
MySuperCoolFormSet = inlineformset_factory(ImportantObject, MyAwesomeObject, extra = 1, form = MyNiftyForm, formset = MyInlineFormSet)
And it works.
Alan
I'm using django modelform inheritence in my modelform but it seems to be not working here is my code sample
class ArticleForm(forms.ModelForm):
title = forms.CharField(required=True)
sites = forms.ModelMultipleChoiceField(required=True, queryset= Sites.objects.all().order_by('name'), widget=forms.SelectMultiple())
class ArticleAddForm(ArticleForm):
class Meta(ArticleForm.Meta):
exclude = ('sites',)
i want to exclude "sites" from "ArticleAddForm" but while validating it is raising form validation error sites field required please help?
ModelForms don't handle inheritance so well, I believe.
Probably the best ou can do is remove the required flag in the child class:
def __init__(self, *args, **kwargs):
super(ArticleAddForm, self).__init__(*args, **kwargs)
self.base_fields['sites'].required = False
self.base_fields['sites'].widget = HiddenInput() # if you want
In your view, you need to initialize the ArticleAddForm with an Article object to fill the blank fields, i.e. the excluded fields. For example:
sites = Sites.objects.all() # modify this according to your needs
article = Article(title='', sites=sites)
form = ArticleAddForm(request.POST, instance=article)
form.save()
I'm using ModelMultipleChoiceField with a large number of objects.
I want to show only the selected objects and let the user remove a choice with js.
To add choices the user will open a popup similar to ManyToManyRawIdWidget.
I can limit the queryset to the selected choices in the init of the form with:
def __init__(self, *args, **kwargs):
super(FormName, self).__init__(*args, **kwargs)
self.fields['field_name'].queryset = self.instance.field_name
But this will require manual setting on every form.
Is it possible to extend the ModelMultipleChoiceField to get the queryset from the field choices?
I think that I need to extend ModelChoiceIterator but couldn't understand how to access the module instance.
Thanks
i am not sure if this is what you are looking for, but if you want the same "list-shuttle" than in auth/user/permissions you should try this;
class MyForm(forms.ModelForm):
myfield = forms.ModelMultipleChoiceField(
queryset = Category.objects.all(),
widget = admin.widgets.FilteredSelectMultiple(
_('myfield'), False),
required = False,
)
class MyAdmin(admin.ModelAdmin):
form = MyForm