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()
Related
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
Is it possible to change what fields are displayed in a ModelForm, dynamically?
I am trying to show only a small number of fields in a ModelForm when the user adds a new instance (of the Model) from the frontend (using an add form) but larger number of fields when the user edits an instance (using an edit form).
The Form class looks something like this:
class SchoolForm(ModelForm):
class Meta:
model = School
#want to change the fields below dynamically depending on whether its an edit form or add form on the frontend
fields = ['name', 'area', 'capacity', 'num_of_teachers']
widgets = {
'area': CheckboxSelectMultiple
}
labels = {
'name': "Name of the School",
'num_of_teachers': "Total number of teachers",
}
Trying to avoid having two separate classes for add and edit since that doesnt seem DRYish. I found some SO posts with the same question for the admin page where we could override get_form() function but that does not apply here.
Also, this answer suggests using different classes as the normal way and using dynamic forms as an alternative. Perhaps dynamics forms is the way forward here but not entirely sure (I also have overridden __init__() and save() methods on the SchoolForm class).
I'm not suere if is a correct way, but i use some method in class to add fields or delete-it. I used like this:
class someForm(forms.ModelForm):
class Meta:
model = Foo
exclude = {"fieldn0","fieldn1"}
def __init__(self, *args, **kwargs):
super(someForm, self).__init__(*args, **kwargs)
self.fields['foofield1'].widget.attrs.update({'class': 'form-control'})
if self.instance.yourMethod() == "FooReturn":
self.fields['city'].widget.attrs.update({'class': 'form-control'})
else:
if 'city' in self.fields: del self.fields['city']
Hope it helps.
I just researched my "bug" and it turned out to be a new feature in Django 1.9 that CharFields strip spaces by default :
https://docs.djangoproject.com/en/1.9/ref/forms/fields/#django.forms.CharField.strip
The same seams to apply to text fields TextField.
So I found out why Django suddenly behaves differently than before, but is there an easy way to restore the previous default for auto generated admin forms?
I would like to NOT strip spaces while still using the auto generated form from the admin. Is that still possible?
If you are looking for a text/char field and do not want it to strip white spaces you can set strip=False in the constructor method of a form and then use the form in the admin
class YourForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(YourForm, self).__init__(*args, **kwargs)
self.fields['myfield'].strip = False
class Meta:
model = YourModel
fields = "__all__"
You can then use this form in the admin by specifying form=YourForm in the admin.py file.
Try using this:
# fields.py
from django.db.models import TextField
class NonStrippingTextField(TextField):
"""A TextField that does not strip whitespace at the beginning/end of
it's value. Might be important for markup/code."""
def formfield(self, **kwargs):
kwargs['strip'] = False
return super(NonStrippingTextField, self).formfield(**kwargs)
And in your model:
class MyModel(models.Model):
# ...
my_field = NonStrippingTextField()
strip=False
in the model field for CharFields.
Django TextField do not support this stripping feature so you have to do it on your own. You can use the strip method.
abc.strip()
Seems like the best way to handle this is to create a custom admin form like this:
class CustomForm(forms.ModelForm):
my_field = forms.CharField(strip=False, widget=forms.Textarea)
class Meta:
model = MyModel
exclude = []
This will create a default form with just my_field overwritten with its non stripped version. )this has to be set in the corresponding admin of course. If anybody knows an even simpler version. Please tell me!
You can also achieve this by modifying ModelAdmin.
Overridding formfield_for_dbfield function and setting kwargs['strip'] = False for title field will disable auto trim for it.
#admin.register(Example)
class ExampleAdmin(admin.ModelAdmin):
def formfield_for_dbfield(self, db_field, request, **kwargs):
if db_field.name == 'title':
kwargs['strip'] = False
return super().formfield_for_dbfield(db_field, request, **kwargs)
Ref: https://www.aaronoellis.com/articles/allow-whitespace-to-be-a-valid-charfield-value-in-django-admin
I was having this issue with django-rest model serializer. The data in my text field was stripped of white space. So if you are trying to do this on the serializer level, you can specify the whitespace param on CharField serializer. Here is the source code signature.
And here is the rest-docs on CharField
class SomeSerializer(serializers.ModelSerializer):
content = serializers.CharField(trim_whitespace=False)
class Meta:
model = YourModel
fields = ["content"]
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"
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