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