I have a form which is having a 'price', 'tax' and 'discount' fields (IntegerFields). And then one more read-only field will be there called 'total_price'.
while we enter the 'price', 'discount' and 'tax', automatically 'total_price' value should display. If we change the 'discount' or 'price' then 'total_price' also change immediately.
After seeing the final price, we can click the 'Save' button.
How to attain this in Django admin?
To do this, you will have to add custom Javascript code to your admin page.
Here's what you can do:
Your admin may look like this:
@admin.register(YourModel)
class YourModelAdmin(admin.ModelAdmin):
# some code here...
readonly_fields = ('total_price', )
def total_price(self, obj):
# return whatever initial value you want
return obj.price - obj.price*obj.discount
# This is important - adding custom script to admin page
@property
def media(self):
media = super().media
media._js.append('js/your-custom-script.js')
return media
Remember that js/your-custom-script.js
must be in your static files folder.
UPDATE:
Instead of overwriting media
property, you can include your JS using Meta
nested class:
class YourModelAdmin(admin.ModelAdmin):
...
class Media:
js = (
'path-to-your-static-script-file.js',
)
The last step is to write a script to update value of total_price
field whenever some other field is changed.
Example: if you want to change total_price
whenever price
is changed, your script can look like this:
if (!$) {
$ = django.jQuery;
}
$(document).ready(function(){
// Add event listener to "price" input
$("#id_price").change(function(e){
// Get entered value
let price = parseFloat($(this).val());
// Get discount value from another field
let discount = parseFloat($("#id_discount").val())
// Compute total price in whatever way you want
let total_price = price - price*discount;
// Set value in read-only "total_price" field.
$("div.field-total_price").find("div.readonly").text(total_price);
});
})
If you want to update total_price
when discount
or tax
fields are changed, simply add event listeners to them.