191👍
Either in your admin.py
or in a separate forms.py
you can add a ModelForm
class and then declare your extra fields inside that as you normally would. I’ve also given an example of how you might 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 have the extra fields appearing in the admin just:
- Edit your
admin.py
and set the form property to refer to the form you created above. - Include your new fields in your fields or fieldsets declaration.
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 of YourModelForm
.
53👍
It it possible to do in the admin, but there is not a very straightforward way to it. Also, I would like to advice to keep most business logic in your models, so you won’t be dependent on the Django Admin.
Maybe it would be easier (and maybe even better) if you have the two seperate fields on your model. Then add a method on 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 the admin you can add the combined_fields()
as a readonly 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 store the combined_fields
in the database you could also save it when you save the model:
def save(self, *args, **kwargs):
self.field3 = self.combined_fields()
super(MyModel, self).save(*args, **kwargs)
- [Django]-Specifying limit and offset in Django QuerySet wont work
- [Django]-Django simple_tag and setting context variables
- [Django]-Django: How to format a DateField's date representation?
10👍
Django 2.1.1
The primary answer got me halfway to answering my question. It did not help me save the result to a field in my actual model. In my case I wanted a textfield that a user could enter data into, then when a save occurred the data would be processed and the result put into a field in the model and saved. While the original answer showed how to get the value from the extra field, it did not show how to save it back to the model at least in Django 2.1.1
This takes the value from an unbound custom field, processes, and saves it into my real description field:
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__"
- [Django]-Are sessions needed for python-social-auth
- [Django]-Django Footer and header on each page with {% extends }
- [Django]-Constructing Django filter queries dynamically with args and kwargs
4👍
You can always create new admin template, and do what you need in your admin_view
(override the admin add URL to your admin_view
):
url(r'^admin/mymodel/mymodel/add/$','admin_views.add_my_special_model')
- [Django]-Strings won't be translated in Django using format function available in Python 2.7
- [Django]-Django Rest Framework Conditional Field on Serializer
- [Django]-How to print BASE_DIR from settings.py from django app in terminal?
3👍
If you absolutely only want to store the combined field on the model and not the two seperate fields, you could do something like this:
- Create a custom form using the
form
attribute on yourModelAdmin
. ModelAdmin.form - Parse the custom fields in the
save_formset
method on yourModelAdmin
. ModelAdmin.save_model(request, obj, form, change)
I never done something like this so I’m not completely sure how it will work out.
- [Django]-Django REST Framework (DRF): Set current user id as field value
- [Django]-Where should signal handlers live in a django project?
- [Django]-Bypass confirmation prompt for pip uninstall
3👍
The first (highest score) solution (https://stackoverflow.com/a/23337009/10843740) was accurate, but I have more.
If you declare fields by code, that solution works perfectly, but what if you want to build those dynamically?
In this case, creating fields in the __init__
function for the ModelForm
won’t work. You will need to pass a custom metaclass
and override the declared_fields
in the __new__
function!
Here is a sample:
class YourCustomMetaClass(forms.models.ModelFormMetaclass):
"""
For dynamically creating fields in ModelForm to be shown on the admin panel,
you must override the `declared_fields` property of the metaclass.
"""
def __new__(mcs, name, bases, attrs):
new_class = super(NamedTimingMetaClass, mcs).__new__(
mcs, name, bases, attrs)
# Adding fields dynamically.
new_class.declared_fields.update(...)
return new_class
# don't forget to pass the metaclass
class YourModelForm(forms.ModelForm, metaclass=YourCustomMetaClass):
"""
`metaclass=YourCustomMetaClass` is where the magic happens!
"""
# delcare static fields here
class Meta:
model = YourModel
fields = '__all__'
- [Django]-Django models: Only permit one entry in a model?
- [Django]-Django Form File Field disappears on form error
- [Django]-CORS error while consuming calling REST API with React
1👍
This is what I did to add the custom form field "extra_field" which is not the part of the model "MyModel" as shown below:
# "admin.py"
from django.contrib import admin
from django import forms
from .models import MyModel
class MyModelForm(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().save(commit=commit)
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
- [Django]-Django Form File Field disappears on form error
- [Django]-Fastest way to get the first object from a queryset in django?
- [Django]-Speeding up Django Testing
0👍
You might get help from my answer at :
my response previous on multicheckchoice custom field
You can also extend multiple forms having different custom fields and then assigning them to your inlines class like stackedinline or tabularinline:
form =
This way you can avoid formset complication where you need to add multiple custom fields from multiple models.
so your modeladmin looks like:
inlines = [form1inline, form2inline,…]
In my previous response to the link here, you will find init and save methods.
init will load when you view the page and save will send it to database.
in these two methods you can do your logic to add strings and then save thereafter view it back in Django admin change_form or change_list depending where you want.
list_display will show your fields on change_list.
Let me know if it helps …
….
class CohortDetailInline3(admin.StackedInline):
model = CohortDetails
form = DisabilityTypesForm
...
class CohortDetailInline2(admin.StackedInline):
model = CohortDetails
form = StudentRPLForm
…
…
@admin.register(Cohort)
class CohortAdmin(admin.ModelAdmin):
form = CityInlineForm
inlines = [uploadInline, cohortDetailInline1,
CohortDetailInline2, CohortDetailInline3]
list_select_related = True
list_display = ['rto_student_code', 'first_name', 'family_name',]
…
- [Django]-How to Unit test with different settings in Django?
- [Django]-Django REST Framework: adding additional field to ModelSerializer
- [Django]-Where should signal handlers live in a django project?