Merge branch 'master' of github.com:tyrelsouza/django-dbfilestorage
This commit is contained in:
commit
f4acb997f2
52
README.md
Normal file
52
README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Django-dbfilestorage
|
||||||
|
|
||||||
|
|
||||||
|
[![CircleCI](https://circleci.com/gh/tyrelsouza/django-dbfilestorage.svg?style=svg)](https://circleci.com/gh/tyrelsouza/django-dbfilestorage)
|
||||||
|
|
||||||
|
Custom file storage for Django that stores file data and content type in the database.
|
||||||
|
Easy to use for testing when you don't care about a filename, and just want to test file data.
|
||||||
|
|
||||||
|
Intended to be used in tests, never in production.
|
||||||
|
|
||||||
|
## INSTALLATION
|
||||||
|
|
||||||
|
In your project's `settings.py` file, add `'dbfilestorage'` to your `INSTALLED_APPS`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
INSTALLED_APPS = (
|
||||||
|
...
|
||||||
|
'dbfilestorage'
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, if you want to set this globally, set the setting:
|
||||||
|
|
||||||
|
```python
|
||||||
|
DEFAULT_FILE_STORAGE='dbfilestorage.storage.DBFileStorage'
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can set it individually on a field: [Django Docs](https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.FileField.storage)
|
||||||
|
|
||||||
|
```python
|
||||||
|
from dbfilestorage.storage import DBFileStorage
|
||||||
|
|
||||||
|
class SomeClass(models.Model):
|
||||||
|
file = models.FileField(upload_to=u'anywhere',
|
||||||
|
storage=DBFileStorage())
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- More Tests
|
||||||
|
- Test that this works on a fake model, not just the storage file.
|
||||||
|
- Different django and different python versions.
|
||||||
|
- Store original filename in a field, maybe?
|
||||||
|
- Use original filename instead, so it honors the "upload_to" parameter.
|
||||||
|
|
||||||
|
|
||||||
|
## CHANGELOG
|
||||||
|
|
||||||
|
- 2016-12-08 [Tyrel Souza] Add more documentation.
|
||||||
|
- 2016-12-07 [Tyrel Souza] Update Readme, move to github, gitlab wasn't functioning properly.
|
||||||
|
- 2016-12-07 [Tyrel Souza] Initial commits and basic project setup
|
26
README.rst
26
README.rst
@ -1,26 +0,0 @@
|
|||||||
Django-dbfilestorage
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
.. image:: https://circleci.com/gh/tyrelsouza/django-dbfilestorage/tree/master.svg?style=svg
|
|
||||||
:target: https://circleci.com/gh/tyrelsouza/django-dbfilestorage/tree/master
|
|
||||||
|
|
||||||
Custom file storage for Django that stores file data and content type in the database.
|
|
||||||
Easy to use for testing when you don't care about a filename, and just want to test file data.
|
|
||||||
|
|
||||||
Intended to be used in tests, never in production.
|
|
||||||
|
|
||||||
|
|
||||||
TODO
|
|
||||||
====
|
|
||||||
|
|
||||||
More Tests
|
|
||||||
Different django and different python versions.
|
|
||||||
Store original filename in a field, maybe?
|
|
||||||
Use original filename instead, so it honors the "upload_to" parameter.
|
|
||||||
|
|
||||||
|
|
||||||
CHANGELOG
|
|
||||||
=========
|
|
||||||
|
|
||||||
- 2016-12-07 [Tyrel Souza] Update Readme, move to github, gitlab wasn't functioning properly.
|
|
||||||
- 2016-12-07 [Tyrel Souza] Initial commits and basic project setup
|
|
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='DBFile',
|
name='DBFile',
|
||||||
fields=[
|
fields=[
|
||||||
('name', models.CharField(max_length=100,
|
('name', models.CharField(max_length=100,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False)),
|
serialize=False)),
|
||||||
('content_type', models.CharField(max_length=100)),
|
('content_type', models.CharField(max_length=100)),
|
||||||
|
@ -31,9 +31,12 @@ class DBStorage(Storage):
|
|||||||
"""
|
"""
|
||||||
The save method does most of the 'magic'.
|
The save method does most of the 'magic'.
|
||||||
It stores the contents of the file as a base64 string.
|
It stores the contents of the file as a base64 string.
|
||||||
It then takes the filename, and tries to get the mimetype from that (for rendering)
|
It then takes the filename, and tries to get the mimetype from that
|
||||||
Then it takes the md5 of the read file and uses that as the "unique" key to access the file.
|
(for rendering)
|
||||||
Then it checks if the file exists and if it doesn't, it will create the entry in the database.
|
Then it takes the md5 of the read file and uses that as the "unique"
|
||||||
|
key to access the file.
|
||||||
|
Then it checks if the file exists and if it doesn't, it will create
|
||||||
|
the entry in the database.
|
||||||
|
|
||||||
:return str: the name(md5) to look up the file by.
|
:return str: the name(md5) to look up the file by.
|
||||||
"""
|
"""
|
||||||
|
25
docs/conf.py
25
docs/conf.py
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Django DBStorage documentation build configuration file, created by
|
# Django DBFileStorage documentation build configuration file, created by
|
||||||
# sphinx-quickstart on Wed Dec 7 14:50:49 2016.
|
# sphinx-quickstart on Wed Dec 7 14:50:49 2016.
|
||||||
#
|
#
|
||||||
# This file is execfile()d with the current directory set to its
|
# This file is execfile()d with the current directory set to its
|
||||||
@ -45,7 +45,7 @@ source_suffix = '.rst'
|
|||||||
master_doc = 'index'
|
master_doc = 'index'
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u'Django DBStorage'
|
project = u'Django DBFileStorage'
|
||||||
copyright = u'2016, Tyrel Souza'
|
copyright = u'2016, Tyrel Souza'
|
||||||
author = u'Tyrel Souza'
|
author = u'Tyrel Souza'
|
||||||
|
|
||||||
@ -54,9 +54,9 @@ author = u'Tyrel Souza'
|
|||||||
# built documents.
|
# built documents.
|
||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
version = u'0.0.1'
|
version = u'0.0.3'
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = u'0.0.1'
|
release = u'0.0.3'
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
@ -82,7 +82,7 @@ todo_include_todos = False
|
|||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
#
|
#
|
||||||
html_theme = 'alabaster'
|
html_theme = 'nature'
|
||||||
|
|
||||||
# Theme options are theme-specific and customize the look and feel of a theme
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
# further. For a list of options available for each theme, see the
|
# further. For a list of options available for each theme, see the
|
||||||
@ -99,7 +99,7 @@ html_static_path = ['_static']
|
|||||||
# -- Options for HTMLHelp output ------------------------------------------
|
# -- Options for HTMLHelp output ------------------------------------------
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = 'DjangoDBStoragedoc'
|
htmlhelp_basename = 'DjangoDBFileStoragedoc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
@ -126,7 +126,9 @@ latex_elements = {
|
|||||||
# (source start file, target name, title,
|
# (source start file, target name, title,
|
||||||
# author, documentclass [howto, manual, or own class]).
|
# author, documentclass [howto, manual, or own class]).
|
||||||
latex_documents = [
|
latex_documents = [
|
||||||
(master_doc, 'DjangoDBStorage.tex', u'Django DBStorage Documentation',
|
(master_doc,
|
||||||
|
'DjangoDBFileStorage.tex',
|
||||||
|
u'Django DBFileStorage Documentation',
|
||||||
u'Tyrel Souza', 'manual'),
|
u'Tyrel Souza', 'manual'),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -136,7 +138,7 @@ latex_documents = [
|
|||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
man_pages = [
|
man_pages = [
|
||||||
(master_doc, 'djangodbstorage', u'Django DBStorage Documentation',
|
(master_doc, 'djangodbstorage', u'Django DBFileStorage Documentation',
|
||||||
[author], 1)
|
[author], 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -147,10 +149,7 @@ man_pages = [
|
|||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
# dir menu entry, description, category)
|
# dir menu entry, description, category)
|
||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
(master_doc, 'DjangoDBStorage', u'Django DBStorage Documentation',
|
(master_doc, 'DjangoDBFileStorage', u'Django DBFileStorage Documentation',
|
||||||
author, 'DjangoDBStorage', 'One line description of project.',
|
author, 'DjangoDBFileStorage', 'One line description of project.',
|
||||||
'Miscellaneous'),
|
'Miscellaneous'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
29
docs/dbfilestorage/installation.rst
Normal file
29
docs/dbfilestorage/installation.rst
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
In your project's `settings.py` file, add `'dbfilestorage'` to your `INSTALLED_APPS`:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
INSTALLED_APPS = (
|
||||||
|
...
|
||||||
|
'dbfilestorage'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
Next, if you want to set this globally, set the setting:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
DEFAULT_FILE_STORAGE='dbfilestorage.storage.DBFileStorage'
|
||||||
|
|
||||||
|
|
||||||
|
Or you can set it individually on a field: `Django Docs <https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.FileField.storage>`_
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
from dbfilestorage.storage import DBFileStorage
|
||||||
|
|
||||||
|
class SomeClass(models.Model):
|
||||||
|
file = models.FileField(upload_to=u'anywhere',
|
||||||
|
storage=DBFileStorage())
|
65
docs/dbfilestorage/usage.rst
Normal file
65
docs/dbfilestorage/usage.rst
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
Backstory
|
||||||
|
---------
|
||||||
|
|
||||||
|
The use case for this may be very small. At my company for our project we have
|
||||||
|
a giant test fixture, and we test file upload and creation. At the inception of
|
||||||
|
this module, I was working on changing our backend system to support Amazon S3
|
||||||
|
filestorage. I was getting frustrated with testing the assumption that a file
|
||||||
|
would exist on the hard drive, and not "somewhere else" so I started this module.
|
||||||
|
|
||||||
|
At first, I was going to use the BLOB field, but the way that we dump and load
|
||||||
|
our test fixtures didn't dump BLOBs by default.
|
||||||
|
|
||||||
|
Thus, the current implementation was born.
|
||||||
|
|
||||||
|
|
||||||
|
On to the Usage!
|
||||||
|
----------------
|
||||||
|
|
||||||
|
The normal usage for this is almost exactly the same for local file storage.
|
||||||
|
The user will upload a file the exact same way, and except for the url being an
|
||||||
|
md5 string, everything works exactly the same.
|
||||||
|
|
||||||
|
Saving file
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
The save method does most of the 'magic'. It stores the contents of the file as
|
||||||
|
a base64 string. It then takes the filename, and tries to get the mimetype from
|
||||||
|
that (for rendering purposes). Then it takes the md5 of the read file and uses
|
||||||
|
that as the "unique" key to access the file. Then it checks if the file exists
|
||||||
|
and if it doesn't, it will create the entry in the database.
|
||||||
|
|
||||||
|
Example from Tests:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
DBFileStorage.save("kris.jpg", file_object)
|
||||||
|
|
||||||
|
There will then be an entry in the database `50f3bfa6b91668789acab5f0a733fb3a`
|
||||||
|
that has the content of the `kris.jpg` file in it, with the content_type of
|
||||||
|
`image/jpeg`.
|
||||||
|
|
||||||
|
Opening file
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
This file will then be accessible by the model field's `.open()` as normal.
|
||||||
|
The `.open()` returns a ContentFile of the base64 decoded data, so it should
|
||||||
|
work everywhere that a normal file would.
|
||||||
|
|
||||||
|
Viewing file with browser ( .url() )
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
I've provided a `dbstorage_file` view that will render the file.
|
||||||
|
|
||||||
|
It gets the file object from the database referenced by the md5 (the
|
||||||
|
filefield.url() will provide this) automatically. It then returns a
|
||||||
|
HttpResponse of the decoded file and content type. Very straightforward.
|
||||||
|
|
||||||
|
Other operations
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Everything else, such as `.path()`, `.delete()`, `.size()`, `.exists()` are
|
||||||
|
exactly the same, in usage as normal.
|
@ -3,13 +3,15 @@
|
|||||||
You can adapt this file completely to your liking, but it should at least
|
You can adapt this file completely to your liking, but it should at least
|
||||||
contain the root `toctree` directive.
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
Welcome to Django DB File Storage's documentation!
|
Django DB File Storage
|
||||||
==================================================
|
======================
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: Contents:
|
:caption: Contents:
|
||||||
|
|
||||||
|
dbfilestorage/installation
|
||||||
|
dbfilestorage/usage
|
||||||
|
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
@ -13,9 +13,10 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.conf.urls import url, include
|
1. Import the include() function: from django.conf.urls import url, include
|
||||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url, include
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
|
url(r'^dbfilestorage/', include('dbfilestorage.urls')),
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user