31

I have a Django admin form. And now I want to fill it's initial field with data based on my model. So I tried this:

class OrderForm(forms.ModelForm): class Meta: model = Order email = CharField(initial="null", widget=Textarea(attrs={'rows': 30, 'cols': 100})) def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) products = kwargs['instance'].products.all() self.message = purchase_message % ( "".join(["<li>" + p.name + ": " + str(p.price) + "</li>" for p in products]), reduce(lambda x, y:x + y.price, products, 0) ) # and here I have a message in self.message variable super(OrderForm, self).__init__(*args, **kwargs) 

At this point i don't know how to access email field to set it's initial value before widget is rendered. How can i do this?

6 Answers 6

79

Assuming the value is based on 'request' you should use this:

class MyModelAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): form = super(MyModelAdmin, self).get_form(request, obj, **kwargs) form.base_fields['my_field_name'].initial = 'abcd' return form 
Sign up to request clarification or add additional context in comments.

Comments

52

Since Django 1.7 there is a function get_changeform_initial_data in ModelAdmin that sets initial form values:

def get_changeform_initial_data(self, request): return {'name': 'custom_initial_value'} 

EDIT: Apart from that, @Paul Kenjora's answer applies anyway, which might be useful if you already override get_form.

In case of inline (InlineModelAdmin) there is no get_changeform_initial_data. You can override get_formset and set formset.form.base_fields['my_field_name'].initial.

6 Comments

It doesn't work if you are using a custom form class for the model admin
@ozgur naturally. If you use a custom form class then just use get_form as recommended in another answer. If not though, there is absolutely no reason to do so.
thanks, this helped me. so many other posts have way more complicated ways of doing this.
Note that get_changeform_initial_data() is only called when adding new objects, not when changing existing ones. See source (Django 3.2).
Thank you for mentioning what to do in case of inline, I have been searching about it for a while
|
9

I'm not too sure what you need to set email to, but You can set the initial values in lots of different places.

Your function def init() isn't indented correctly which i guess is a typo? Also, why are you specifically giving the email form field a TextInput? It already renders this widget by default

You can set the email's initial value in your form's initialized (def __ init __(self))

(self.fields['email'].widget).initial_value = "something" 

or in the model.py

email = models.CharField(default="something") 

or as you have in forms.py

email = models.CharField(initial="something") 

Comments

7

I needed the first solution of pastylegs since the other ones overwrite the whole Widget including, for example, the help text. However, it didn't work for me as he posted it. Instead, I had to do this:

self.fields['email'].initial = 'something' 

In my case, I was trying to do a personalized auto-increment(based on current data and not a simple default) in a field of a django admin form.

Comments

4

This code is worked for me (Django 1.11):

from django import forms class MyAdminForm(forms.ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.initial['field_name'] = 'initial_value' 

Comments

0

I don't know why but form.base_fields['my_field_name'].initial = 'abcd' doesn't really work in my case at all. I came up with the following code below after a few days.

models.py:

class Record(SaveMixin, models.Model): class ViewStatus(models.IntegerChoices): DRAFT = 0, "Черновик" PUBLISHED = 1, "Опубликовано" is_published = models.BooleanField(choices=ViewStatus.choices, verbose_name="Статус", default=ViewStatus.DRAFT ) 

admin.py:

def get_form(self, request, obj=None, **kwargs): form = super(MealRecordAdmin, self).get_form(request, obj, **kwargs) if obj: if obj.is_published: initial_choices = form.base_fields['is_published'].choices published_choice = initial_choices.pop(Record.ViewStatus.PUBLISHED) initial_choices.insert(0, published_choice) return form 

Now, if user changes an already existing model instance through admin panel, the default value for "is_published" is being taken from DataBase. If I'm wrong about anything, tell me, please, about it

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.