Django自定义文件存储系统增量编号格式异常问题求助
Fixing Duplicate File Naming with Incrementing Numbers in Your Custom Storage System
Looks like the issue comes from how you're extracting and incrementing the file number—your current logic keeps appending new numbers to the existing filename instead of replacing the old increment value. Let's break down what's wrong and fix it:
What's Causing the Broken Naming?
- Fragile Fixed Index: Using
filename.split('_')[19]is super unreliable. The number of underscores in your filename won't always be 20, so this will either throw an index error or pull the wrong value entirely. - Incorrect Root Filename Handling: When you process an existing file like
nameofthefile_1.txt, you're treatingnameofthefile_1as the new file root. Then you add2to it, creatingnameofthefile_1_2.txt—and this pattern repeats every time, leading to the nested numbers you're seeing. - No Loop for Edge Cases: If a file gets deleted (e.g.,
nameofthefile_2.txtis removed), your current code would skip straight to3instead of filling the gap (though this is a minor point compared to the main issue).
Corrected Implementation
Here's a revised version of your CustomStorage class that properly handles incrementing numbers without nesting them:
import os import re from django.core.files.storage import FileSystemStorage class CustomStorage(FileSystemStorage): def get_available_name(self, filename, max_length=None): # Split the filename into directory, root, and extension dir_name, file_name = os.path.split(filename) file_root, file_ext = os.path.splitext(file_name) # Extract the base name and current increment number # Match the trailing "_数字" pattern using regex num_match = re.search(r'_(\d+)$', file_root) if num_match: base_name = file_root[:num_match.start()] current_num = int(num_match.group(1)) else: # Fallback: if no number suffix exists (though your initial filename has _1) base_name = file_root current_num = 0 # Loop until we find a filename that doesn't exist while self.exists(os.path.join(dir_name, f"{base_name}_{current_num}{file_ext}")): current_num += 1 # Build and return the final available filename new_filename = f"{base_name}_{current_num}{file_ext}" return os.path.join(dir_name, new_filename) if dir_name else new_filename def user_directory_path(instance, filename): extension = filename.split('.')[-1] filename = f"file_{instance.identification}_1.{extension}" return f'folder/{instance.user}/{filename}'
How This Works
- Regex for Reliable Number Extraction: The regex
r'_(\d+)$'looks for a number at the end of the filename root (after an underscore). This safely pulls the increment value regardless of how many other underscores are in the filename. - Proper Base Name Separation: We separate the core filename (e.g.,
file_xxxfromfile_xxx_1) so we can replace the increment number instead of appending to it. - Loop to Ensure Availability: The while loop checks if the generated filename exists, incrementing the number until it finds one that's free. This handles edge cases like deleted files or manually added versions.
With this code, uploading duplicates will generate filenames like file_xxx_1.txt, file_xxx_2.txt, file_xxx_3.txt exactly as you expected.
内容的提问来源于stack exchange,提问作者Kome Gognome
相关产品推荐
相关产品推荐

