3

I have typical model inheritance in my project:

class A(models.Model):
    boolean_field = models.BooleanField(default=True)

class B(A):
    some_other_field = models.CharField()

I want to override default value of boolean_field in class B, how can I do it?

I think that could be tricky thing to do on a database layer, so maybe at least I can simply override that default value in Django admin (I mean in ModelAdmin form for class B).

Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
nukl
  • 10,073
  • 15
  • 42
  • 58

3 Answers3

5

As you suggest, I think the easiest approach is to change the model form used for the B model in the django admin.

To change the initial value of the form field, you can either redefine the field, or override the __init__ method.

class BForm(forms.ModelForm):
    # either redefine the boolean field
    boolean_field = models.BooleanField(initial=False)

    class Meta:
        model = B

    # or override the __init__ method and set initial=False
    # this is a bit more complicated but less repetitive
    def __init__(self, *args, **kwargs):
        super(BForm, self).__init__(*args, **kwargs)
        self.fields['boolean_field'].initial = False

Using your custom model form in the django admin is easy!

class BAdmin(admin.ModelAdmin):
    form = BForm

admin.site.register(B, BAdmin)
Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • The `__init__` way is better, so the field in the model can be changed without having to manually reflect those changes in the modelform, since only one parameter is changed. – Armando Pérez Marqués Jun 24 '12 at 14:42
1
class A(models.Model):
    boolean_field = models.BooleanField(default=True)
    def __unicode__(self):
        return self. boolean_field 


class B():
    some_other_field = models.CharField()
    default_fiel_from_bool = models.ForeignKey(A)
jai
  • 11
  • 1
  • 2
1

From this answer, the easiest way I've found is to override the function get_changeform_initial_data.

Here's how I applied it to my project.

In this example, I have a ORM class called Step and an Admin class called StepAdmin. The function get_latest_step_order gets the step_order from the latest object in the table.

By overriding the get_changeform_initial_data function in the admin class I'm able to set the step order for each new object that's created in the admin screen.

class Step(models.Model):
    step_name = models.CharField(max_length=200)
    step_status = models.ForeignKey(StepStatus, null=True)
    step_order = models.IntegerField()


def get_latest_step_order():
    return Step.objects.latest('step_order').step_order+1

class StepAdmin(admin.ModelAdmin):
    fields = ["step_name","step_status","step_order"]

    def get_changeform_initial_data(self, request):
        return {
            'step_order': get_latest_step_order()
        }
djvg
  • 11,722
  • 5
  • 72
  • 103
FistOfFury
  • 6,735
  • 7
  • 49
  • 57
  • Only update I'd make to this is to also call the super function first to get the main default dictionary for other values too. Something like: `defaults = super().get_changeform_initial_data(request)` `defaults['step_order'] = get_latest_step_order()` – Dfranc3373 Jun 16 '21 at 21:48