Set initial value for Model Form field

I’m trying to simply set the default, initial value for an entry in a model form. I have tried all kinds of proposed solutions from other searches, but nothing seems to work. The field in the template always appears blank and this is a required entry. Here is the code for the form.

class ImageUploadForm(forms.ModelForm):
    class Meta:
        model = Image
        fields = ['pic', 'starting_label']

    def __init__(self, *args, **kwargs):
        super(ImageUploadForm, self).__init__(*args, **kwargs)
        self.fields['starting_label'].value = 1000
        self.fields['pic'] = forms.FileField(widget=forms.TextInput(attrs={
            'name': 'images',
            'type': 'File',
            'class': 'form-control',
            'multiple': True,
        }), label='Upload Image(s)')
        self.fields['starting_label'] = forms.IntegerField(label='Starting Label No',
                                                           initial=1000,
                                                           min_value=1,
                                                           max_value=10000)

The value that I am trying to set is for the starting_label field. I’m trying to set the initial value to 1000.

This is the html from the template.

            <div class="mb-3">
                <label for="{{ form.form_Name.id_for_label }}" class="form-label">Starting Label No.</label>
                {{ form.starting_label }}
            </div>

Any ideas on what I am missing here?

Thanks!
Bob

This isn’t the right attribute, the attribute would be initial:
self.fields['starting_label'].initial = 1000

Beyond that, I can’t recreate the symptoms you’re describing. Both variations work for me, leading me to believe that the issue is external to what you’ve posted so far. (Could be the view, the template, the model, or even that you’re not rendering the form that you think you’re rendering.)

1 Like

I believe I had set .initial at one point and that didn’t work, but as you said it could be the view or the mddel.

Here is the code for the view.

def album_images_upload(request, pk):
    form = ImageUploadForm(request.POST, request.FILES, initial={'starting_label': 1000})

    context = {"form": form,
               "album_section": album_section,
               "album_title": album.album_title,
               "have_token": have_token,}
    return render (request, 'Albums/album_images_upload.html', context)

Here is the model.

class Image(models.Model):
    pic = models.FileField(upload_to='images/')
    starting_label = models.IntegerField(null=False, blank=False, default=1000)

I still can’t recreate your symptoms from what you’re showing here. I may need to see the complete view.

Make sure you don’t have anything like duplicate view or form definitions in your files.

Try printing the form to the console before it’s rendered.

Also, verify the rendered HTML as it appears in the browser.

In the debugger this is what I am seeing for the fields attribute of the form.

{'pic': <input type="File" name="pic" name="images" class="form-control" multiple required aria-invalid="true" id="id_pic">, 'starting_label': <input type="number" name="starting_label" min="1" max="10000" required aria-invalid="true" id="id_starting_label">}

This is the full view.

def album_images_upload(request, pk):
    form = ImageUploadForm(request.POST, request.FILES)
    refresh_token = get_user_token(request)
    if request.method == 'POST':
        images = request.FILES.getlist('pic')
        album_section = Album_Section.objects.get(pk=pk)
        try:
            label_number = int(form.data.get('starting_label'))
        except:
            label_number = 1000
        #label_number = 1000
        sort_position = 100000
        fs = FileSystemStorage()
        dbx = DropboxContainer(USER_APP_KEY, USER_APP_SECRET, refresh_token)
        # Create a remote file operations object
        rfo = RemoteFileOperations()
        rfo.dropbox_object = dbx
        rfo.remote_source_type = "Dropbox"
        for image in images:
            image_ins = Image(pic = image)
            file_name = image.name
            # Use this name and then upload to dropbox
            image_ins.filename = file_name
            image_ins.save()
            file_name = image_ins.pic.file.name
            try:
                file_from = file_name
                uploaded_file_url = fs.url(file_from)
                file_full_path = fs.path(file_from)
                base_file_name = os.path.basename(file_full_path).split('/')[-1]
                extension = os.path.splitext(file_name)[1]
                base_file_name = ''.join(random.choices(string.ascii_uppercase +
                                                        string.digits, k=25)) + extension
                file_to = f"/uploads/{request.user}/{base_file_name}"
                rfo.file_upload(file_full_path, file_to)
                if rfo.exception_string == "":
                    # Create a shared link to this file
                    shared_link_meta = rfo.file_shared_link(file_to)
                    album_image = Album_Section_Entry()
                    album_image.album_section_id = album_section
                    album_image.label_number = str(label_number)
                    album_image.entry_description = "(update)"
                    album_image.notes = f"Multi-file upload - file name: {file_name}"
                    album_image.dropbox_filename = file_to
                    album_image.base_filename = base_file_name
                    album_image.dropbox_shared_link = str(shared_link_meta.url)
                    album_image.sort_position = sort_position
                    album_image.save()
                    label_number += 1
                    sort_position += 1000
                else:
                    uploaded = f"No - Error during upload ({rfo.exception_string})"
            except:
                uploaded = f"no - Error during upload attempt ({rfo.exception_string})"
            image_ins.delete()

        return redirect("album_gallery", album_section_id=album_section.id)
    album_section = Album_Section.objects.get(pk=pk)
    album = Album.objects.get(pk=album_section.album_id.pk)
    source = request.session['album_source']
    have_token = (refresh_token != "")

    context = {"form": form,
               "album_section": album_section,
               "album_title": album.album_title,
               "have_token": have_token,}
    return render (request, 'Albums/album_images_upload.html', context)

What version of Python and Django are you using?

You have verified that you do not have more than one ImageUploadForm defined anywhere in your project? (Or that you don’t have 2 __init__ methods defined in the form.)

Python version: 3.12.5
Django version: 5

Yes, no duplicate ImageUploadForm and only one init.

If you add a print(form) on the line before the context = statement, what output is generated?

What is rendered if your template renders the form as {{ form }}?

First, thanks for all of the replies. This as usual is very helpful Ken.

I change the template to {{ Form }} and it rendered similar to the formatted version, but still with no entry in the starting_label field.

Please post here what you’re getting for both the print statement and the rendered html.

This is the form as rendered to the console from the Print() statement.

<div>
    <label for="id_pic">Upload Image(s):</label>
<ul class="errorlist"><li>This field is required.</li></ul>
<input type="File" name="pic" name="images" class="form-control" multiple required aria-invalid="true" id="id_pic">
    
</div>
  <div>
    <label for="id_starting_label">Starting Label No:</label>
<ul class="errorlist"><li>This field is required.</li></ul>
<input type="number" name="starting_label" min="1" max="10000" required aria-invalid="true" id="id_starting_label">
    
      
    
</div>

This is the actual HTML rendered.

    <div class="container mx-3">
        <div>
    <label for="id_pic">Upload Image(s):</label>


<ul class="errorlist"><li>This field is required.</li></ul>
<input type="File" name="pic" name="images" class="form-control" multiple required aria-invalid="true" id="id_pic">
    
</div>

  <div>
    <label for="id_starting_label">Starting Label No:</label>


<ul class="errorlist"><li>This field is required.</li></ul>
<input type="number" name="starting_label" min="1" max="10000" required aria-invalid="true" id="id_starting_label">
    
      
    
</div>

Those prints are from a POST, not a GET. Please show the output from the GET request.

Okay, sorry Ken, but I’m not sure what you mean by that, or how you can tell those aren’t from the GET. The print statement is outside if this IF statement.

if request.method == 'POST':

That line never executes. I use

Print(form)

right before rendering the form for input. I haven’t clicked the submit button at this point.

Ahh - I see what’s happening now.

Move your form binding (form = ImageUploadForm(request.POST, request.FILES)) to inside the if request.method == 'POST': block.

Bind an initial / raw form (form = ImageUploadForm()) outside that conditional, or in an else clause for that conditional.

Okay, I did what you recommended and it worked!!

After looking at this, it makes sense. I should be sending a raw form on the GET and then loading the posted form on the POST.

As always, thanks for all of your help Ken! I really appreciate it!

Bob