You can relatively easily upload a file to Django and save it into a location in your filesystem using a Model
. And it's quite standard to set up serving those uploaded files when users need to view them.
An exceptionally specific, yet I think common case is for those files to be only viewable by the admins. For instance, if the user needs to upload a verification document for the admins to review before granting the user full access.
In those cases, the standard process of setting up static file deployment might not be enough. Those uploaded media files should only be downloadable from the admin interface. Let's see how this can be accomplished using a custom admin view.
Prerequisites
Firstly, you would need to set up a custom admin site as described here.
Secondly, your Model should contain a FileField
:
class CustomUserProfile(models.Model):
# [...] Other fields
id_proof = models.FileField(upload_to='id_proof')
models.py
View
You will need a view that will take as a parameter the primary key of the object and will return the bytes of the file. An HttpResponse
with the file contents along with some additional headers will do the trick.
class IdProofView(View):
def get(self, request, pk):
user_profile = CustomUserProfile.objects.get(pk=pk)
filename = os.path.basename(user_profile.id_proof.name)
response = HttpResponse(user_profile.id_proof)
response['Content-Disposition'] = \
f'attachment; filename={filename}'
return response
views.py
Then wire it up in your custom admin's URL dispatcher (see this for how to set up a custom admin site). Notice that you are wrapping the call to your view with admin_view()
. This will protect it from unauthorized access. Only staff members will be able to download the file which is the behavior we want.
class CustomAdminSite(AdminSite):
def get_urls(self):
urls = super().get_urls()
my_urls = [
# [...] Other views for your custom admin
path('id_proof/<int:pk>', \
self.admin_view(IdProofView.as_view()), name='id_proof'),
]
return my_urls + urls
admin.py
ModelAdmin
Finally, we need to show the "secure" link to the file in the admin interface. We need a ModelAdmin
that generates the link, if it exists, and shows it as a read-only property. Optionally, you can hide the default field in the ModelAdmin
that will not work anyway, if you haven't set up media files serving.
class CustomUserProfileModelAdmin(admin.ModelAdmin):
readonly_fields = ('id_proof_url',)
exclude = ('id_proof',)
def id_proof_url(self, instance):
if instance.id_proof is None:
return '-'
return format_html(
f'<a href="{reverse("admin:id_proof", \
kwargs={"pk": instance.pk})}"target="_blank">Download</a>',
)
admin.register(CustomUser, CustomUserModelAdmin)
admin.py
Hopefully, you got an idea of how to securely serve files defined in models to staff users via the admin interface.
Happy coding!
Top comments (0)