我想创建一个包含字符串的文件,并允许用户在管理员详细页面上单击按钮时下载该文件。 有什么建议吗?
可能要向表单添加html?但是我怎么做呢?我是Django的新手。
我想创建一个包含字符串的文件,并允许用户在管理员详细页面上单击按钮时下载该文件。 有什么建议吗?
可能要向表单添加html?但是我怎么做呢?我是Django的新手。
您可以按照以下方式进行:
class YourAdmin(ModelAdmin):
# add the link to the various fields attributes (fieldsets if necessary)
readonly_fields = ('download_link',)
fields = (..., 'download_link', ...)
# add custom view to urls
def get_urls(self):
urls = super(YourAdmin, self).get_urls()
urls += [
url(r'^download-file/(?P<pk>\d+)$', self.download_file,
name='applabel_modelname_download-file'),
]
return urls
# custom "field" that returns a link to the custom function
def download_link(self, obj):
return format_html(
'<a href="{}">Download file</a>',
reverse('admin:applabel_modelname_download-file', args=[obj.pk])
)
download_link.short_description = "Download file"
# add custom view function that downloads the file
def download_file(self, request, pk):
response = HttpResponse(content_type='application/force-download')
response['Content-Disposition'] = 'attachment; filename="whatever.txt"')
# generate dynamic file content using object pk
response.write('whatever content')
return response
admin:applabel_modelname_download-file
是做什么的吗? - Michaelreverse
或 url
模板标签所使用。常见的管理视图遵循 applabel_modelname_viewname
模式。这就是为什么我使用它的原因。 - user2390182Model.__meta.app_label
的值作为 applabel
,并将实际模型名称转换为小写字母作为 modelname
。就像你一样,我写了 download-file
。我有什么遗漏吗? - Michaeldownload_link
函数中,加入if obj.id is not None then return link
。否则返回“ - ”。 - Yosef SL@staff_member_required
装饰器(例如)才能防止匿名和非工作人员请求访问。如果您什么都不做,那么该文件下载将对 所有人 开放。 - fechnertmodels.py
字段中,添加以下代码片段。from django.utils.safestring import mark_safe
def fieldname_download(self):
return mark_safe('<a href="/media/{0}" download>{1}</a>'.format(
self.fieldname, self.fieldname))
fieldname_download.short_description = 'Download Fieldname'
admin.py
中,为该模型添加此字段到 readonly_fields 中。readonly_fields = ('fieldname_download', )
settings.py
文件中,您需要指定一个根路径,用于存放文件,并指定一个基本URL来访问它们:MEDIA_ROOT=(str, 'path/to/your/media/directory/'),
MEDIA_URL=(str,'/media/'),
fieldname_download
添加到 fields
属性中,你知道为什么吗? - Michael关于将下载链接作为新字段添加到详情页,有两种答案,比在AdminFileWidget
中添加下载链接更容易。我写下这个答案是为了帮助需要在AdminFileWidget
中添加下载链接的人。
最终结果如下:
models.py
:class Attachment(models.Model):
name = models.CharField(max_length=100,
verbose_name='name')
file = models.FileField(upload_to=attachment_file,
null=True,
verbose_name='file ')
2 views.py:
class AttachmentView(BaseContextMixin, DetailView):
queryset = Attachment.objects.all()
slug_field = 'id'
def get(self, request, *args, **kwargs):
instance = self.get_object()
if settings.DEBUG:
response = HttpResponse(instance.file, content_type='application/force-download')
else:
# x-sendfile is a module of apache,you can replace it with something else
response = HttpResponse(content_type='application/force-download')
response['X-Sendfile'] = instance.file.path
response['Content-Disposition'] = 'attachment; filename={}'.format(urlquote(instance.filename))
return response
3 urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('attachment/<int:pk>/', AttachmentView.as_view(), name='attachment'),
]
4 admin.py
from django.urls import reverse
from django.contrib import admin
from django.utils.html import format_html
from django.contrib.admin import widgets
class DownloadFileWidget(widgets.AdminFileWidget):
id = None
template_name = 'widgets/download_file_input.html'
def __init__(self, id, attrs=None):
self.id = id
super().__init__(attrs)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
print(self, name, value, attrs, self.id)
context['download_url'] = reverse('attachment', kwargs={'pk': self.id})
return context
class AttachmentAdmin(admin.ModelAdmin):
list_display = ['id', 'name', '_get_download_url']
search_fields = ('name',)
my_id_for_formfield = None
def get_form(self, request, obj=None, **kwargs):
if obj:
self.my_id_for_formfield = obj.id
return super(AttachmentAdmin, self).get_form(request, obj=obj, **kwargs)
def formfield_for_dbfield(self, db_field, **kwargs):
if self.my_id_for_formfield:
if db_field.name == 'file':
kwargs['widget'] = DownloadFileWidget(id=self.my_id_for_formfield)
return super(AttachmentAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def _get_download_url(self, instance):
return format_html('<a href="{}">{}</a>', reverse('attachment', kwargs={'pk': instance.id}), instance.filename)
_get_download_url.short_description = 'download'
admin.site.register(Attachment, AttachmentAdmin)
5 download_file_input.html
{% include "admin/widgets/clearable_file_input.html" %}
<a href="{{ download_url }}">Download {{ widget.value }}</a>
就这些!