Recover Custom Field when Editing Django Admin Form
Given the current models in models.py:
from django import forms
from django.db import models
from decimal import Decimal
from datetime import datetime, date
class Order (models.Model):
assignment = models.ForeignKey("Assignment", on_delete=models.RESTRICT)
qty = models.PositiveIntegerField(default=1)
order_date = models.DateField()
price = models.DecimalField(max_digits=10, decimal_places=2)
class Assignment (models.Model):
assig_year = models.PositiveSmallIntegerField()
customer = models.ForeignKey("Customer", on_delete=models.CASCADE)
agent = models.ForeignKey("Agent", on_delete=models.CASCADE)
class Agent (models.Model):
name = models.CharField(max_length=32)
surname = models.CharField(max_length=32)
class Customer (models.Model):
name = models.CharField(max_length=64)
I need to provide users with an admin custom form which allows to create and update orders in a more intuitive way. In order to do that, I exclude the assignment field (which bounds a Customer with a Sales Agent for a given year, but may not be so obvious to fill in for a user) and include a custom field for the user to select just a Customer instead. Based on this input and the order date, I internally look for the specific assignment that fulfills this criteria and assign it to the order to be stored in the Database. It looks like this:
admin.py
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.contrib import admin
from django.db.models import CharField
from django import forms
from django.db import models
from .models import Customer, Assignment, Order
class OrderForm(forms.ModelForm):
customers_list = forms.ModelChoiceField(queryset = Customer.objects.all())
class Meta:
model = Order
exclude = (
'assignment',
)
def save(self, commit=True):
# Create an Order instance but do not commit to the DB yet
obj: Order = super().save(commit=False)
# Look for the associated assignment. If it doesn't exist, an error is raised
try:
assignment = Assignment.objects.get(assig_year=obj.order_date.year, customer=self.cleaned_data['customers_list'])
except ObjectDoesNotExist:
raise ValidationError('No assignment found')
# Add the assignment reference to the order and save it
obj.assignment = assignment
obj.save()
return obj
def clean(self):
cleaned_data = self.cleaned_data
date_form = cleaned_data['order_date']
customer_form = cleaned_data['customers_list']
try:
cleaned_data['assignment'] = Assignment.objects.get(assig_year=date_form.year, customer=customer_form.id)
except ObjectDoesNotExist:
raise ValidationError('No assignment found')
# Then call the clean() method of the super class
super(OrderForm, self).clean()
# Finally, return the cleaned_data
return cleaned_data
class OrderAdmin(admin.ModelAdmin):
form = OrderForm
fieldsets = (
('Order Data:', {
'fields': ( 'customers_list', 'qty', 'order_date', 'price', )
}),
)
Everything works fine when creating a new order; however, if I enter into a previously created register in Admin mode, the Customer custom field is not automatically populated and I do not know how to recover its original value. Any ideas?