You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

django-tinymce结合django-filebrowser无图片上传按钮问题求助

Django-TinyMCE 与 django-filebrowser 集成问题:图片对话框无上传按钮

我正在为博客的文本编辑器集成django-tinymce与django-filebrowser,实现媒体文件插入功能。目前整体运行看似正常,但点击编辑器中的图片按钮后,弹出的对话框里没有文件上传按钮。查过相关论坛帖子,没找到解决办法,以下是我的配置信息:

settings.py 配置

INSTALLED_APPS = [
    # file-browser
    'grappelli',
    'filebrowser',
...
    'tinymce',
...]

STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'


#django-filebrowser:

# Path to filebrowser static files
FILEBROWSER_DIRECTORY = 'filebrowser/'
FILEBROWSER_STATIC_URL = STATIC_URL + 'filebrowser/'
FILEBROWSER_MEDIA_ROOT = BASE_DIR / 'media/uploads/'
FILEBROWSER_MEDIA_URL = '/filebrowser/media/'
FILEBROWSER_SORT_BY = 'date'
FILEBROWSER_MAX_UPLOAD_SIZE = 10485760  # 10 MB
EXTENSIONS = {
    'Image': ['.jpg','.jpeg','.gif','.png','.tif','.tiff'],
    'Video': ['.mov','.wmv','.mpeg','.mpg','.avi','.rm'],
    'Audio': ['.mp3','.mp4','.wav','.aiff','.midi','.m4p'],
    'Document': ['.pdf','.doc','.rtf','.txt','.xls','.csv','.docx','.xlsx']
}
SELECT_FORMATS = {
    'File': ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'zip', 'rar', 'tar', 'gz', 'bz2', 'csv'],
    'Image': ['jpg', 'jpeg', 'png', 'gif', 'tif', 'tiff'],
    'Video': ['swf', 'flv', 'mpg', 'mpeg', 'mp4', 'mov', 'avi', 'wmv'],
}


#django-tinymce
TINYMCE_JS_URL = 'https://cdn.tiny.cloud/1/{api-key}/tinymce/5/tinymce.min.js?referrerpolicy=origin'

TINYMCE_DEFAULT_CONFIG = {
    "theme": "silver",
    "height": 500,
    "menubar": True,
    "plugins": "advlist,autolink,lists,link,image,charmap,print,preview,anchor,searchreplace,visualblocks,code,fullscreen,insertdatetime,media,table,paste,code,help,wordcount,"
    "searchreplace,visualblocks,code,fullscreen,insertdatetime,media,table,paste,"
    "code,help,wordcount",
    "toolbar": "undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | image | help | imageupload",
    "image_upload_url": "/media/uploads/images/",
    "file_picker_callback": "upload_image",
    'file_browser_callback': 'mce_filebrowser'
}


TINYMCE_SPELLCHECKER = False
TINYMCE_COMPRESSOR = False
TINYMCE_FILEBROWSER = True

项目 urls.py 配置

...
from filebrowser.sites import site

...
urlpatterns = i18n_patterns(
    path('admin/filebrowser/', site.urls),
    path('grappelli/', include('grappelli.urls')),
...
    path('tinymce/', include('tinymce.urls')),
...

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

models.py 配置

...
from filebrowser.fields import FileBrowseField


class Post(TranslatableModel):

...
    translations = TranslatedFields(
        title = models.CharField(_('title'), max_length=250, blank=True, null=True),
        slug = models.SlugField(_('slug'), max_length=250, allow_unicode=True, blank=True, null=True),
        body = models.TextField(_('body'), blank=True, null=True)
    )


class Media(models.Model):
    MEDIA_TYPES = (
        ('image', 'Image'),
        ('video', 'Video'),
        ('audio', 'Audio'),
    )

    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='media')
    media_file = FileBrowseField("File", max_length=200, directory="media/")
    media_type = models.CharField(max_length=10, choices=MEDIA_TYPES, default='image')

    def __str__(self):
        return f"{self.media_type} for post {self.post.title}"

forms.py 配置

...
from django.conf import settings
...
from tinymce.widgets import TinyMCE



class PostForm(TranslatableModelForm):
    body = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}, mce_attrs={
                                                'file_browser_callback': 'filebrowser',
                                                'file_browser_callback_url': '/admin/filebrowser/browse/',
                                                'file_picker_callback': 'filebrowser',
                                                'file_picker_callback_url': '/admin/filebrowser/browse/',
                                            }))
    language = LanguageField()

    class Meta:
        model = Post
        fields = ['featured_image', 'language', 'title', 'body', 'tags', 'publish', 'status']
        widgets = {
            'title': forms.TextInput(attrs={'class': 'hidden'}),
            'slug': forms.TextInput(attrs={'class': 'hidden'}),
        }

解决方法

  1. 修正 TinyMCE 回调配置
    TinyMCE 5+版本优先使用file_picker_callback,且你当前配置的upload_image未定义,会导致回调失效。修改TINYMCE_DEFAULT_CONFIG:

    TINYMCE_DEFAULT_CONFIG = {
        # 保留原有其他配置
        "file_picker_callback": lambda callback, value, meta: mce_filebrowser(callback, value, meta),
        # 移除 file_browser_callback 配置
    }
    
  2. 统一表单回调设置
    forms.py中同时设置两种回调会造成冲突,保留file_picker_callback即可:

    body = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}, mce_attrs={
                                                'file_picker_callback': 'mce_filebrowser',
                                                'file_picker_callback_url': '/admin/filebrowser/browse/',
                                            }))
    
  3. 检查文件目录与权限

    • 确保media/uploads目录存在,运行mkdir -p media/uploads并给目录设置读写权限
    • 核对FILEBROWSER_MEDIA_ROOT与FILEBROWSER_DIRECTORY的路径匹配,保证目录结构正确
  4. 重新收集静态文件
    执行python manage.py collectstatic,确保grappelli和filebrowser的静态资源被正确加载,避免因资源缺失导致按钮不显示

  5. 验证 filebrowser 独立功能
    直接访问/admin/filebrowser/browse/,检查是否能看到上传按钮。如果这里也没有,确认:

    • INSTALLED_APPS中grappelli在filebrowser之前(顺序不能错)
    • 当前登录用户拥有filebrowser的操作权限

内容的提问来源于stack exchange,提问作者Rodrigo Yanez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 17:44:54