如何修改Django Admin变更页面的文件链接为FTP路径
Hey there! Let's break down your problem and the solutions available:
核心结论
Both modifying the URL path (via a custom storage backend) and template overriding work here. Which one you pick depends on whether you want a global fix for all file fields or customized control for a specific model/field.
方法1:修改URL路径(自定义存储后端)
This is the cleaner approach if you want all uploaded files in Django Admin to show FTP links by default. Django uses your file storage class's url() method to generate file links in the Admin—so you can override this method to return an FTP path instead of a local URL.
Here's how to implement it:
- Create a custom FTP storage class in your app (e.g.,
storages.py):
from django.core.files.storage import Storage from django.conf import settings from django.utils.deconstruct import deconstructible @deconstructible class FTPStorage(Storage): def __init__(self, ftp_host=None, ftp_port=None, ftp_user=None, ftp_pass=None, ftp_folder=None): self.ftp_host = ftp_host or settings.FTP_HOST self.ftp_port = ftp_port or settings.FTP_PORT self.ftp_user = ftp_user or settings.FTP_USER self.ftp_pass = ftp_pass or settings.FTP_PASS self.ftp_folder = ftp_folder or settings.FTP_FOLDER def url(self, name): # Generate the FTP link format you need return f"ftp://{self.ftp_user}:{self.ftp_pass}@{self.ftp_host}:{self.ftp_port}/{self.ftp_folder}/{name}" # You'll also need to implement required Storage methods for FTP operations def _open(self, name, mode='rb'): # Logic to open the file from your FTP server pass def _save(self, name, content): # Logic to upload the file to your FTP server pass def exists(self, name): # Check if the file already exists on FTP pass
- Update your
settings.pyto use this storage by default:
DEFAULT_FILE_STORAGE = 'your_app.storages.FTPStorage' # Add your FTP configuration FTP_HOST = 'your-ftp-host-address' FTP_PORT = 21 FTP_USER = 'your-ftp-username' FTP_PASS = 'your-ftp-password' FTP_FOLDER = 'your-target-folder-on-ftp'
Once set up, Django Admin will automatically use the FTP link generated by your storage class for all file fields.
方法2:模板重写(针对特定模型/字段)
If you only need to adjust the link for a specific model (like your Software model's profile_pics field), template overriding gives you full control over the display.
Here's the step-by-step:
- Create a custom change form template for your model. In your app, create the path
templates/admin/basic_app/software/change_form.html:
{% extends "admin/change_form.html" %} {% block field_sets %} {% for fieldset in adminform %} {% for line in fieldset %} {% for field in line %} {% if field.field.name == 'profile_pics' %} <div class="form-row"> <label>{{ field.label }}:</label> {% if field.value %} <!-- Replace with your FTP link format --> <a href="ftp://{{ ftp_user }}:{{ ftp_pass }}@{{ ftp_host }}:{{ ftp_port }}/{{ ftp_folder }}/{{ field.value.name }}" target="_blank"> {{ field.value.name }} </a> {% endif %} {{ field.field }} </div> {% else %} {{ field }} {% endif %} {% endfor %} {% endfor %} {% endfor %} {% endblock %}
- Pass FTP credentials to the template via your ModelAdmin class. Update your
admin.py:
from django.contrib import admin from django.conf import settings from .models import Software class SoftwareAdmin(admin.ModelAdmin): # Point to your custom template change_form_template = 'admin/basic_app/software/change_form.html' def changeform_view(self, request, object_id=None, form_url='', extra_context=None): extra_context = extra_context or {} # Add FTP configs to the template context extra_context.update({ 'ftp_host': settings.FTP_HOST, 'ftp_port': settings.FTP_PORT, 'ftp_user': settings.FTP_USER, 'ftp_pass': settings.FTP_PASS, 'ftp_folder': settings.FTP_FOLDER, }) return super().changeform_view(request, object_id, form_url, extra_context) admin.site.register(Software, SoftwareAdmin)
小提醒
Keep in mind that some modern browsers might block FTP links or require a default FTP client to open them directly. Test the link behavior across your target browsers to ensure it works as expected.
内容的提问来源于stack exchange,提问作者mebetop

