edoburu / django-private-storage Goto Github PK
View Code? Open in Web Editor NEWPrivate media file storage for Django projects
License: Apache License 2.0
Private media file storage for Django projects
License: Apache License 2.0
django-private-storage 1.2.3 is incompatible with Django 2.0 yet, while Django 2.0 already exists in some repo files it can mislead some users.
Specific incompatibilities I've found:
permissions.py
Using User.is_authenticated() and User.is_anonymous() as methods rather than properties is no longer supported.
fields.py
FileField methods get_directory_name() and get_filename() are removed.
I could miss something else.
Hope you're going to add support of Django 2.0 soon.
.
Is it possible to get the object that contains the PrivateFileField requested in custom function for checking permissions?
I struggled to get Unicode filenames to work when serving with X-Sendfile via Apache. (Where it worked in the development server.) This was with Python 2 (and Django 1.11). I haven't tested with later versions.
It turned out that when setting a header on a django.http.HttpResponse object to a Unicode string the value instead became a str object which didn't work well when the response object was later used. It works for me by just changing response['X-Sendfile'] = private_file.full_path
(which was a unicode) by adding .encode('utf-8')
to the end of it in serve
in ApacheXSendFileServer
in servers.py
.
This is the quick fix for me (except it really wasn't quick :-) which might need embellishing to work with different versions and maybe to check what the actual encoding of filenames should be, but hopefully useful as a start or as something to copy for others with the same problem.
@vdboor Thanks for the great package!
It's not an issue actually, but a feature request. Do you consider adding DRF support shortly? Problem with that implementation that DRF has own auth system – https://www.django-rest-framework.org/api-guide/authentication/#setting-the-authentication-scheme.
Best regards!
This tool is doing almost what I need, but I'd like to be able to serve static (PDF) files with the private-storage folder without uploading via the Django API or website. (e.g. rsync
files from another machine)
I've tried to put files into the private-storage folder, but they don't show up in the admin dashboard. Is it possible to just serve whatever is in the folder?
First, thank you very much for this great plugin!
While testing the deployment of an app using django-private-storage
in an environment with the recently release Django 3.0, I noticed that django-private-storage
attempts to import django.utils.six
in fields.py
.
As Django 3.0 has removed private Python 2 compatibility APIs like django.utils.six
, trying to import it raises a ModuleNotFoundError
.
See https://docs.djangoproject.com/en/3.0/releases/3.0/#removed-private-python-2-compatibility-apis for details; the Django release notes suggest to either remove usage of this vendored library or switching to using six directly.
It appears that allow_staff() is being called from within PrivateStorageView as a member function, and self is being passed along to the function in addition to private_file parameter.
To replicate the problem, check out https://github.com/mmclark/privstor
$ git clone https://github.com/mmclark/privstor
$ mkvirtualenv privstor
$ cd privstor ; pip install -r requirements.txt
$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver
Environment:
Request Method: GET
Request URL: http://localhost:8000/private-media/meetings/testing.pdf
Django Version: 1.10.5
Python Version: 2.7.12
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'private_storage',
'meetings']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
39. response = get_response(request)
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/home/mmclark/.virtualenvs/privstor/lib/python2.7/site-packages/private_storage/views.py" in get
40. if not self.can_access_file(private_file):
Exception Type: TypeError at /private-media/meetings/testing.pdf
Exception Value: allow_staff() takes exactly 1 argument (2 given)
Do I have to name the view as 'send_private_file' ?
I get the following error
django.urls.exceptions.NoReverseMatch: Reverse for 'serve_private_file' not found. 'serve_private_file' is not a valid view function or pattern name.
Do Private storage support mp3 format files?
The commit 713f918 added a decorator that sets the cache-control and expires headers to explicitly disable caching on the client.
While I can see how this may be useful in some cases, it doesn't work for my use case. I want to be able to allow a client which had an authorized user access an image, to keep accessing it for a short while after, thus I'd like to customize the cache-control's max-age and expires values to something else (perhaps something closer to what the S3 token expiry is set to).
How do you feel about allowing the header values to be customized? Or perhaps allowing users to specify the expiry time delta (in seconds?) or None (to disable cache) ? If you agree with one of these solutions, I would love to submit a pull request.
I have integrated drf authentication and private-storage-detail-view by making a subclass like this
class DRFObjectDownloadView(views.APIView, PrivateStorageDetailView):
"""
A wrapper to integrate rest-framework authentication
and the permissions system with private-storage. Implements the
same by subclassing APIView. `can_access_file` is overwritten to
always return True
"""
def can_access_file(self, private_file):
# ensure that can_access_file always returns
# True as drf handles authentication already
return True
and then I inherit this class in two views, one for viewing the files and another one for downloading.
class UploadFileServeView(DRFObjectDownloadView):
model = Upload
slug_field = 'file'
# make sure that files can only be viewed in-line
# with browsers. Files can only be served via this view
content_disposition = 'inline'
queryset = Upload.objects.all()
permission_classes = [IsAuthenticated, ReadUploads]
def get_object(self, queryset=None):
return get_object_or_404(Upload, file=self.kwargs['path'])
class UploadFileDownloadView(UploadFileServeView):
# make sure that files can only be downloaded.
# Files cannot be served via this view
content_disposition = 'attachment'
permission_classes = [IsAuthenticated, DownloadFiles]
However, when the user has the permissions and downloads the file, I cannot open the file again.
I uploaded an mp4 file once and then downloaded it from the view, but then the file was corrupted.
And the mp4 file couldn't be played inside the browser too.
my models
class Upload(BaseModel):
objects = UploadManager()
size = models.PositiveBigIntegerField()
channel = models.ForeignKey('uploads.Channel', on_delete=models.CASCADE, editable=False)
name = models.CharField(max_length=100, default='untitled', validators=[MinLengthValidator(2)])
box = models.ForeignKey('uploads.Box', on_delete=models.CASCADE, editable=False)
owner = models.ForeignKey('users.User', on_delete=models.CASCADE, editable=False)
# need to make storage private
# by default we store to media dir now
file = PrivateFileField(upload_to='uploads/', storage=private_storage)
REQUIRED_FIELDS = [file, owner]
url patterns
# protected file-service with permission-checking
re_path('^private/(?P<path>.*)$', upload_views.UploadFileServeView.as_view()),
re_path('^downloads/(?P<path>.*)$', upload_views.UploadFileDownloadView.as_view()),
Hi,
I deployed my Django + Private-Storage page on an Apache server + mod_wsgi combi on a CentOS maschine. Unfortunately, when I set
PRIVATE_STORAGE_SERVER = 'apache'
the downloaded files are all empty. Does anyone has an idea, what might be wrong?
When uploading a file with non-ascii characters, I get the following error:
UnicodeEncodeError at /url_removed/
'ascii' codec can't encode character '\xe9' in position 56: ordinal not in range(128)
Request Method: POST
Request URL: url_removed
Django Version: 3.2
Exception Type: UnicodeEncodeError
Exception Value:
'ascii' codec can't encode character '\xe9' in position 56: ordinal not in range(128)
These are the steps to reproduce the issue:
id_file = PrivateFileField(upload_to='id/', max_file_size=size_3mb, null=True, blank=True)
and add it to a form.Where can I set the encoding codec?
Python 3.8.5 and Django 3.2
Hello,
on django 4.1 i get this error
was_modified_since() takes from 0 to 2 positional arguments but 3 were given
i think the problem is here
def serve(private_file): # Support If-Last-Modified mtime = private_file.modified_time.timestamp() size = private_file.size if not was_modified_since(private_file.request.META.get('HTTP_IF_MODIFIED_SINCE'), mtime, size): return HttpResponseNotModified()
here the reference of django changelog https://docs.djangoproject.com/en/4.1/releases/4.1/#miscellaneous
Testing PRIVATE_STORAGE_S3_REVERSE_PROXY = True
.
It saves the files properly on S3, yet, when retrieving the file, when it tries to access the django sever view, it gives 404. Do I have to configure a reverse proxy with apache/nginx/caddy or the django server view actually fetches the object from S3 and proxies to the client?
Hi, today I got the following error:
File: /usr/lib/python3.8/site-packages/private_storage/fields.py
, line 16, in
from django.utils.six import string_types
ModuleNotFoundError: No module named 'django.utils.six'
I've got auto-updates on my machine and a reboot caused this error to pop up.
I have Django 3.0.2 installed
sorry, I just realised it's a duplicate of #41
Hello.
Can you add tutorial for creating your own custom permissions?
I wan't add this permission in chat where person to person. And only owner and person can see this file in this chat.
Using custom PrivateFileSystemStorage
with a complex kwarg location arises “problem” doesn’t read nested subfolders within the folder containing private files.
# Storage
DOCUMENT_SECOND_STORAGE: ty.Final[PrivateFileSystemStorage] = PrivateFileSystemStorage(
location=f'{settings.PRIVATE_STORAGE_ROOT}/docs_second',
base_url='/storage/docs_second/',
)
# View url
urlpatterns = (
re_path('^docs-second/(?P<path>.*)', DocumentSecondStorageView.as_view()),
)
As for url http://localhost/storage/docs-second/1_TPgao9l4.jpeg
within the folder however won’t go into subfolders to look for the file.
How do I get it fixed correctly?
Hey,
If the model has a uuid as a primary key, this library gives an error.
'UUID' object is not iterable
Request Method: | POST
<...>
'UUID' object is not iterable
<...> site-packages/private_storage/fields.py, line 90, in generate_filename
I haven't checked the function, but as I understand, it's trying to generate a filename from a pk?
I'm getting this warning:
RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().
I think that changing the import in private_storage.fields
should fix it.
class DocumentoGenerico(RegistroMixin):
def dame_path(self):
path = ['/']
try:
path.append('{}'.format(self.content_type.app_label))
path.append('{}'.format(self.content_type.model))
path.append('registro-{}'.format(self.object_id))
except AttributeError:
path.append('genericos')
return path
documento = PrivateFileField(_('Documento'), upload_subfolder=dame_path, null=True, blank=True)
It returns SuspiciousFileOperation in Django 2.2.20 and upper. Bug or configuration error? Thx.
Sadly the documentation doesn't cover how to actually implement your own retrieve class.
I tried many solutions, but nothing worked. It would be nice if someone could add a more detailed explanation to the readme or explain it at least here.
Here are my tries, so you don't have to waste your time by trying out none working solutions:
path("private-media/", MaterialDownloadView.as_view(), name="serve_private_file"),
path("private-media/", include(private_storage.urls)),
url(r'(?P<path>.*)', MaterialDownloadView.as_view(), name="serve_private_file"),
path("private-media/", include(private_storage.urls)),
url(r'(.*)(?P<path>.*)', MaterialDownloadView.as_view(), name="serve_private_file"),
path("private-media/", include(private_storage.urls)),
path("private-media/", MaterialDownloadView.as_view()),
path("private-media/", include(private_storage.urls)),
Hi,
I'm making a simple function from defining an upload subfolder:
def subfolder(instance):
return os.path.join("statements", str(instance.ID))
The path where the file is uploaded is: s/t/a/t/e/m/e/n/t/s/2/my_file.pdf
How can I fix it?
I try to upload multiple files with [(https://docs.djangoproject.com/en/3.0/topics/http/file-uploads/#uploading-multiple-files)] and I don't know how to adapt the post part of the documentation.
Thanks
Steps to reproduce:
PrivateModel
and set one field as PrivateFileField
TestModel
and reference PrivateModel
as a foreign keyTestModel
keeping PrivateModel
as inlinePRIVATE_STORAGE_ROOT
path and manually delete the file associated with newly created TestModel
instanceExpected outcome:
The PrivateModel
instance marked for deletion is removed and TestModel
instance is updated successfully
Actual Outcome:
Throws FileNotFoundError
I found myself writing custom logic to sanitize a filename that would be downloadable on major browsers and able to open it on any operating system. This value is then provided to the content_disposition_filename
attribute of the PrivateStorageDetailView
class.
Instead, I think PrivateStorageDetailView._encode_filename_header
should take care of it instead. We can do this by stripping permitted tokens as per RFC6266. I found the rfc6266 package on PYPI does exactly that, so one option would be to use it and then call in on build_header
with the optional filename_compat
agument whenever we encounter an older browser (UA == MSIE enough ?)
While this may seem like a purely selfish act, it would be lovely for us not to think about content disposition, and browser support, and header specifications at all when an awesome storage package such as this can do it for us 😄 !
First of all, thanks for this great package. This has become super complementary with django-tenants or django-pgschemas.
I happen to use different storages in local development and production. For local development I keep the default file system private storage, while for production I am using a customization of the S3 boto3 file storage.
Because of the way in which the storage is set here:
I am always getting a minor complain from Django in production that I have changes in my models that need migration. The change is basically shifting the file system storage, which is in my migrations, versus the S3 boto3 file storage which is then active.
This is actually a minor thing, nothing breaks here, it's only a polishing request. As a general rule, I think Django models should be done in a way that changing settings doesn't generate new migrations. I wonder if you would be okay to change the linked behavior and use a function instead, which could in turn return the exact same value that is being set here. I think that by using a function, Django won't detect any change in settings and won't think that there is a migration required.
I could open a PR for this if approved. Thanks!
Would I be right in saying that the guide in this repo for proxying with nginx will only work with locally served media?
I assume that's the case, as the /path/to/media must be a local path, not an S3 one.
Do you know how to use nginx as the proxy when using S3 media? I guess I'll need some different config in the nginx location block but I'm not 100% sure what, exactly.
Hi! Thanks for the very useful package. It saved me a lot of time!
I just would like to suggest to add some django-rest-framework support from the box.
You have permission function is_authenticated
, but it is only for Django request, but as I understand DRF has own Request class and own is_authenticated
.
I found a workaround for support.
I just inherited from APIview
and PrivateStorageDetailView
and all works fine.
Is it the right way, or maybe there is a more elegant way.
Hi there,
I see that this project supports different backends for storage systems that one can extend, file system storage and s3 comes with the library itself, so that file system, amazon, digital ocean storage are all covered, but I was wondering if you are planning to add google and azure to the mix, I'm especially asking it in regards to the google part as I almost exclusively use google services in my projects.
Hi!
I just tested this app and it works perfectly but I cant set user upload folders to their username. On default django FileField I used custom function which returns path with username and date:
def func(instance, filename):
time = datetime.now()
return '%s/%s/%s' % (instance.user.username, time.year, filename)
file = PrivateFileField(upload_to=func)
With PrivateFileField above returns and AttributeError: 'function' object has no attribute 'endswith'
Traceback:
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/core/handlers/exception.py" in inner
39. response = get_response(request)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/some/path/to/proj/szcz/views.py" in post
76. PL = Dszcz.objects.create(plik2=myfile, user=request.user, postepowanie_id=int(self.kwargs['postepowanie_id']))
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/manager.py" in manager_method
85. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/query.py" in create
399. obj.save(force_insert=True, using=self.db)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/base.py" in save
796. force_update=force_update, update_fields=update_fields)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/base.py" in save_base
824. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/base.py" in _save_table
908. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/base.py" in _do_insert
947. using=using, raw=raw)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/manager.py" in manager_method
85. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/query.py" in _insert
1045. return query.get_compiler(using=using).execute_sql(return_id)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
1053. for sql, params in self.as_sql():
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in as_sql
1006. for obj in self.query.objs
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in pre_save_val
955. return field.pre_save(obj, add=True)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in pre_save
292. file.save(file.name, file, save=False)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in save
90. name = self.field.generate_filename(self.instance, name)
File "/some/path/to/proj-env/local/lib/python2.7/site-packages/private_storage/fields.py" in generate_filename
74. return smart_str(os.path.join(*dirs))
File "/some/path/to/proj-env/lib/python2.7/posixpath.py" in join
77. elif path == '' or path.endswith('/'):
AFAIK it's not possible to set up a SSECustomerKey
for Server-side encryption with a specific key. It seems django-storages
supports it for writing files but not for reading them.
Do you know how to achieve this?
(Given that the purpose of this package is handling private files, should it support more encryption-related features such as this one?)
Can you please include a tutorial for beginners using django and amazon s3 with this private storate? Thanks!
How exactly is max_file_size
used? As i can see from the Traceback it is supposed to be an integer. What unit does it refer to?
Thanks
Hi, there,
I set my function to define the subfolder like this:
def subfolder(instance):
return os.path.join("files", str(instance.Publisher.id), str(instance.Contract.id))
But when I upload a file I only find one level of subfolder:
contracts1/10/contract.pdf
It should be:
contracts/1/10/contract.pdf
Thanks,
Gregorio
I am using this package in reverse proxy mode, against an S3 bucket. I need to manually get an image from the storage in order to put it in a PDF with reportlab. My fetching function looks like:
def fetch_image(private_image):
from io import BytesIO
from PIL import Image
import requests
response = requests.get(private_image.url)
return Image.open(BytesIO(response.content))
private_image.url
responds with the reverse-proxied url, it's not working for me as I have other checks in place.
I need the actual url of the file, or the actual path of the file, or anything that helps me retrieve the image from the underlying storage. How can I do it?
Defining PrivateFile.content_type
works fine with the DjangoStreamingServer
, but always defaults to application/octet-stream
when using DjangoServer
.
My browser also warns me about this
Resource interpreted as Document but transferred with MIME type application/octet-stream
At present, if a file already exists within the directory with the same name, the new file is renamed. Is there any way to preserve the orginal filename either by deleting the old existing file, renaming the existing file first, sending a sub directory or some other way?
Kind regards.
Dear all,
given the following PrivateStorageDetailView
# views.py
class AttachmentDownloadView(PrivateStorageDetailView):
model = ImageAttachment
model_file_field = 'file'
def get_object(self):
# see: https://github.com/edoburu/django-private-storage/issues/50
return get_object_or_404(self.model, file=self.kwargs['path'])
def can_access_file(self, private_file):
return private_file.request.user.is_authenticated
I always get a Traceback for a Forbidden (Permission denied) request:
Forbidden (Permission denied): /media/attachments/27b5c847-4027-4de9-b26e-98ac028490e8.png
Traceback (most recent call last):
File ".venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File ".venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File ".venv/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File ".venv/lib/python3.9/site-packages/private_storage/views.py", line 158, in get
return super(PrivateStorageDetailView, self).get(request, *args, **kwargs)
File ".venv/lib/python3.9/site-packages/private_storage/views.py", line 73, in get
raise PermissionDenied(self.permission_denied_message)
django.core.exceptions.PermissionDenied: Private storage access denied
[09/Jun/2021 11:27:28] "GET /media/attachments/27b5c847-4027-4de9-b26e-98ac028490e8.png HTTP/1.1" 403 135
How can I handle this exception gracefully (I do not want this uncaught ServerError)?
This is a request-for-enhancement: It would be really nice to have a PrivateImageField that borrows functionality from the standard ImageField class.
as of now it fails with an exception when using latest django storages
hi!.. i need change te permissions of access adn check some parameter in the url, after compare whith my user return the file. Can you explain me how?
thanks
Hello i have a problem with upload_subfolder because the folder is not created correctly.
settings
INSTALLED_APPS += (
'private_storage',
)
PRIVATE_STORAGE_ROOT = str(APPS_DIR('protectedfiles')) #/api/protectedfiles/
PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_staff'
urls:
import private_storage.urls
url(r'^downloads/private/', include(private_storage.urls)),
model:
def dni_dir_path(instance):
return 'user_{0}'.format(str(instance.id))
upload_dni = PrivateFileField(
'documento',
upload_subfolder=dni_dir_path,
blank=True
)
I'm uploading the file from django admin, everything works perfect but the file is uploaded to:
/api/protectedfiles/u/s/e/r/_/1/Test-Disease-List.json instead:
/api/protectedfiles/user_1/Test-Disease-List.json
i'm running django==1.10.7, python 2.7.13 with docker
Thank you!
Hi,
when I make
python manage.py migrate
I get
ImportError: No module named 'apps'
How can I fix it?
Thanks,
Gregorio
uploading private files works just fine but, I want my users who are logged in to the app to be able to download the file from S3.
does this PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_authenticated' enable that? am I missing something here?
how to show it in html? I am confused how the python program shows it in the html.
Can you help to resolve this?
Dear all,
I tried to implement a PrivateStorageDetailView to create a custom can_access_file
function.
I updated my urls.py to reflect the new routing rule:
url(r'^(?P<path>.*)$', MyDocumentDownloadView.as_view(), name='serve_private_file')
When trying to access this view, I get the following error message
Generic detail view MyDocumentDownloadView must be called with either an object pk or a slug in the URLconf
I guess I'm missing something here...
Many thanks for your help
When a user cannot access a file, the class PrivateStorageView
returns an HTTPResponseForbidden
.
This is fine but if I edit the default 403 page for my django project (this can be done simply adding the 403.html
template), this HTTPResponseForbidden
ignores this override and returns this plain text response.
Django also have a builtin exception to handle that, django.core.exceptions.PermissionDenied
. Raising that exception is better in my opinion.
I will send a PR soon.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.