Django admin - adding custom form fields that are not part of the model

I have a model registered on the admin site. One of its fields is a long string expression. I would like to add custom form fields to the add / update page of this model in the admin, which based on these field values ​​will build a long string expression and save it in the corresponding model field.

How can i do this?

UPDATE: Basically, what I am doing is building a mathematical or string expression from characters, the user selects characters (these are custom fields that are not part of the model), and when I click on save, I create a string expression view from the list of characters and save them to the database. I do not want the characters to be part of the model and DB, but only the final expression.

+71
django admin
Jul 30 '13 at 13:12
source share
6 answers

Either in the admin.py file or in a separate forms.py file, you can add the ModelForm class, and then declare your additional fields in it, as usual. I also gave an example of how you can use these values ​​in form.save ():

from django import forms from yourapp.models import YourModel class YourModelForm(forms.ModelForm): extra_field = forms.CharField() def save(self, commit=True): extra_field = self.cleaned_data.get('extra_field', None) # ...do something with extra_field here... return super(YourModelForm, self).save(commit=commit) class Meta: model = YourModel 

To add additional fields to the admin panel, simply:

  1. edit your admin.py and set the form property to link to the form you created above
  2. include your new fields in the declaration of fields or sets of fields

Like this:

 class YourModelAdmin(admin.ModelAdmin): form = YourModelForm fieldsets = ( (None, { 'fields': ('name', 'description', 'extra_field',), }), ) 

UPDATE: in django 1.8 you need to add fields = '__all__' to the metaclass YourModelForm.

+124
Apr 28 '14 at 9:12
source share

This can be done in the admin, but there is no very easy way to it. In addition, I would like to advise you to keep most of the business logic in your models, so you will not be dependent on the Django administrator.

It might be easier (and perhaps even better) if you have two separate fields on your model. Then add a method of your model that combines them.

For example:

 class MyModel(models.model): field1 = models.CharField(max_length=10) field2 = models.CharField(max_length=10) def combined_fields(self): return '{} {}'.format(self.field1, self.field2) 

Then in admin you can add combined_fields() as a read-only field:

 class MyModelAdmin(models.ModelAdmin): list_display = ('field1', 'field2', 'combined_fields') readonly_fields = ('combined_fields',) def combined_fields(self, obj): return obj.combined_fields() 

If you want to save combined_fields in the database, you can also save it when saving the model:

 def save(self, *args, **kwargs): self.field3 = self.combined_fields() super(MyModel, self).save(*args, **kwargs) 
+25
Jul 30 '13 at 13:35
source share

you can always create a new admin template and do what you need in your admin_view (override admin adding url for your admin_view):

  url(r'^admin/mymodel/mymodel/add/$' , 'admin_views.add_my_special_model') 
+4
Aug 21 '14 at 8:38
source share

If you absolutely want to store the combined field on the model, and not two separate fields, you can do something like this:

I have never done anything like this, so I'm not quite sure how it will turn out.

+3
Jul 30 '13 at 14:26
source share

Django 2.1.1. The initial answer gave me half the answer to my question. This did not help me save the result in a field in my real model. In my case, I wanted a text field into which the user could enter data, then when the data was saved, the data was processed, and the result was placed in the field in the model and saved. Although the original answer showed how to get the value from an additional field, it did not show how to save it back to the model, at least in Django 2.1.1.

This takes a value from an unrelated custom field, processes and stores it in the field of my real description:

 class WidgetForm(forms.ModelForm): extra_field = forms.CharField(required=False) def processData(self, input): # example of error handling if False: raise forms.ValidationError('Processing failed!') return input + " has been processed" def save(self, commit=True): extra_field = self.cleaned_data.get('extra_field', None) # self.description = "my result" note that this does not work # Get the form instance so I can write to its fields instance = super(WidgetForm, self).save(commit=commit) # this writes the processed data to the description field instance.description = self.processData(extra_field) if commit: instance.save() return instance class Meta: model = Widget fields = "__all__" 
+1
Sep 21 '18 at 18:41
source share

First add a field to the form

 class CreateForm(forms.ModelForm): extra_field = forms.CharField(label = 'extra_field', required = False) 

Now, when clearing data, you need to extract an additional field from self.data, not self.cleaned_data.

To fix :

  self.data.get('extra_field') 

Wrong

  self.cleaned_data.get('extra_field') 
0
Dec 17 '18 at 13:49
source share



All Articles