SlideShare a Scribd company logo
Files
@jaylett
Files
in an exciting adventure with dinosaurs
Files
in an exciting adventure with dinosaurs
Files
a brief talk
TZ=CET ls -ltr talk/
-rwxr--r-- 1 jaylett django 6 6 Nov 14:01 Files
-rwxr--r-- 1 jaylett django 5 6 Nov 14:02 Files and HTTP
-rwxr--r-- 1 jaylett django 15 6 Nov 14:04 Files in the ORM
-rwxr--r-- 1 jaylett django 13 6 Nov 14:08 Storage backends
-rwxr--r-- 1 jaylett django 25 6 Nov 14:20 Static files
-rwxr--r-- 1 jaylett django 8 6 Nov 14:35 Form media
-rwxr--r-- 1 jaylett django 29 6 Nov 14:40 Asset pipelines
-rwxr--r-- 1 jaylett django 6 6 Nov 14:55 What next?
Files
Python files
Django files
Django files
Awesome!
The File family
• File — or ImageFile, if it might be an image
• ContentFile / SimpleUploadedFile in tests
• which have a different parameter order
• #10541 cannot save file from a pipe
Files and HTTP
UploadedFile
• “behaves somewhat like a file object”
• temporary file and memory variants
• custom upload handlers
forms.FileField
# forms-filefield.py
class FileForm(forms.Form):
uploaded = forms.FileField()
def upload(request):
if request.method == 'POST':
form = FileForm(request.POST, request.FILES)
if form.is_valid():
request.FILES['uploaded'] # do something!
return HttpResponseRedirect('/next/')
else:
form = FileForm()
return render_to_response(
'upload.html',
{'form': form},
)
Again, it works
• #15879 multipart/form-data filename=""

not handled as file
• #17955 Uploading a file without using django forms
• #18150 Uploading a file ending with a

backslash fails
• #20034 Upload handlers provide no way to retrieve
previously parsed POST variables
• #21588 "Modifying upload handlers on the fly"
documentation doesn't replicate internal magic
Files in the ORM
Files in the ORM
# orm-file.py
class Wub(models.Model):
infosheet = models.FileField()
>>> w = Wub(infosheet="relative/to/media/root.pdf")
>>> print w.infosheet.url
https://media.root/relative/to/media/root.pdf
>>> w.infosheet = ContentFile("A boring bit of text",
“file.txt")
>>> print w.infosheet.url
https://media.root/file.txt
• #5619 FileField and ImageField return the wrong path/url

before calling save_FOO_file()
• #10244 FileFields can't be set to NULL in the db
• #13809 FileField open method is only accepting 'rb' modes
• #14039 FileField special-casing breaks MultiValueField including a
FileField
• #13327 FileField/ImageField accessor methods throw unnecessary
exceptions when they are blank or null.
• #17224 determine and document the use of default option in context
of FileField
• #25547 refresh_from_db leaves FieldFile with reference to db_instance
Files in the ORM
# orm-file.py
class Wub(models.Model):
infosheet = models.FileField()
>>> w = Wub(infosheet="relative/to/media/root.pdf")
>>> print w.infosheet.url
http://media.root/relative/to/media/root.pdf
>>> w.infosheet = ContentFile("A boring bit of text",
“file.txt")
>>> print w.infosheet.url
http://media.root/file.txt
>>> w.infosheet = None
>>> print w.infosheet.url
Files in the ORM
# orm-file.py
class Wub(models.Model):
infosheet = models.FileField()
>>> w = Wub(infosheet="relative/to/media/root.pdf")
>>> print w.infosheet.url
http://media.root/relative/to/media/root.pdf
>>> w.infosheet = ContentFile("A boring bit of text",
“file.txt")
>>> print w.infosheet.url
http://media.root/file.txt
>>> w.infosheet = None
>>> print w.infosheet.url
>>> print type(w.infosheet)
FieldFile <class 'django.db.models.fields.files.FieldFile'>
FieldFile
• magical autoconversion for anything (within
reason)
• this happens using FileDescriptor classes
which, well, let’s just ignore that
FileField
# orm-fieldfile.py
class Wub(models.Model):
infosheet = models.FileField()
>>> w = Wub(infosheet="relative/to/media/
root.pdf")
>>> w.infosheet = None
>>> w.infosheet == None
True
>>> w.infosheet is None
False
• #18283 FileField should not reuse FieldFiles
In ModelForms
# modelforms-filefield.py
class Wub(models.Model):
infosheet = models.FileField()
class WubCreate(CreateView):
model = Wub
fields = ['infosheet']
ImageField
# orm-imagefile.py
class Wub(models.Model):
infosheet = models.FileField()
photo = models.ImageField()
>>> w = Wub(infosheet="relative/to/media/
root.pdf", photo="relative/to/media/
root.png")
>>> w.photo.width, w.photo.height
(480, 200)
• #15817 ImageField having

[width|height]_field set sytematically compute

the image dimensions in ModelForm validation
process
• #18543 Non image file can be saved to
ImageField
• #19215 ImageField's “Currently” and “Clear”
Sometimes Don't Appear
• #21548 Add the ability to limit file extensions for
ImageField and FileField
So many classes
So many classes
ImageField
# orm-imagefile-proxies.py
class Wub(models.Model):
infosheet = models.FileField()
photo = models.ImageField(width_field='photo_width',
height_field='photo_height')
photo_width = models.PositiveIntegerField(blank=True)
photo_height = models.PositiveIntegerField(blank=True)
>>> w = Wub(infosheet="relative/to/media/root.pdf",
photo="relative/to/media/root.png")
>>> w.photo.width, w.photo.height
(480, 200)
>>> w.photo_width, w.photo_height
(480, 200)
• #8307 ImageFile use of width_field and
height_field is slow with remote storage
backends
• #13750 ImageField accessing height or width
and then data results in "I/O operation on
closed file”
Storage backends
Storing files
• Stored in MEDIA_ROOT
• Served from MEDIA_URL
• Uses FileSystemStorage…by default
Another abstraction
What can Storage do?
• oriented around files, rather than a general FS API
• open / save / delete / exists / size / path / url
• make an available name, ie one that doesn’t clash
• modified, created, accessed times
• … also listdir
Choosing storage
# configuring-storage-settings.py
DEFAULT_FILE_STORAGE = 'dotted.path.Class'
MEDIA_ROOT = '/my-root'
MEDIA_URL = 'https://media.root/'
class MyStorage(FileSystemStorage):
def __init__(self, **kwargs):
kwargs.setdefault(
'location',
'/my-root'
)
kwargs.setdefault(
'base_url',
'https://media.root/'
)
return super(
MyStorage,
self
).__init__(**kwargs)
Choosing storage
# models.py
from mystorage import BetterStorage
storage_instance = BetterStorage()
class MyModel(models.Model):
upload = models.FileField(
storage=storage_instance
)
• #9586 Shall upload_to return an urlencoded

string or not?
• #12157 FileSystemStorage does file I/O inefficiently, despite
providing options to permit larger blocksizes
• #15799 Document what exception should be raised when trying
to open non-existent file
• #21602 FileSystemStorage._save() Should Save to a Temporary
Filename and Rename to Attempt to be Atomic
• #23759 Storage.get_available_name should preserve all file
extensions, not just the first one
• #23832 Storage API should provide a timezone aware approach
Reasons to override
• Model fields with different options
• Different storage engine entirely
Protected storage
FSS = FileSystemStorage
pstore = FSS(
location=‘/protected’,
base_url="/p/",
)
urlpatterns += patterns(
url(
r'^p/(?P<path>.*)$',
protected,
),
)
class
Profile(models.Model):
resume = FileField(
null=True,
blank=True,
storage=pstore,
)
@login_required
def protected(request,
path):
f = pstore.open(path)
return HttpResponse(
f.chunks()
)
S3BotoStorage
• One of many in django-storages-redux
• Millions of options, somewhat undocumented
• configure with AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY,
AWS_STORAGE_BUCKET_NAME
• defaults for the rest mostly sane
Fun with S3Boto
AWS_S3_CUSTOM_DOMAIN='cdn.eg.com'
AWS_HEADERS={
'Cache-Control': 'max-age=31536000'
} # a year or so
AWS_PRELOAD_METADATA=True
Protected S3 storage
protected_storage = S3BotoStorage(
acl='private',
querystring_auth=True,
querystring_expire=600,
# 10 minutes, try to ensure people
# won’t / can't share
)
model.field.url # works as expected
Code that uses storage
• Please test on both Windows and Linux/Unix
• Please test with something remote like S3Boto
• Please write your own tests to work with different
storage backends
Static files
Helpful assets
staticfiles in 1.3
How it works
<!-- source.html -->
{% load static %}
<img
src='{% static "asset/path.png" %}'
width='200' height='100' alt=''>
<!-- out.html -->
<img
src='https://static.root/asset/path.png'
width='200' height='100' alt=‘'>
In development
collectstatic
• #24336 static server should skip for protocol-
relative STATIC_URL
• #25022 collectstatic create self-referential
symlink
staticfiles in 1.4
staticfiles in 1.4
• #23563 Make `staticfiles_storage` a public API
• #25484 static template tag outputs invalid HTML
if storage class's url() returns a URI with '&'
characters.
I make it sound bad
Really, it’s not
Still a moderately bad time
Still a moderately bad time
Serving assets best practice
Serving assets best practice
Serving assets best practice
Cached (1.4) / Manifest (1.7)
• Cache uses the main cache, or a dedicated one
• Manifest writes a JSON manifest file to the
configured storage backend
The problem
<!-- hashed-assets.html -->
<script src=“/static/admin/js/
collapse.min.c1a27df1b997.js”>
<script src=“/admin/editorial/
article/2/autosave_variables.js">
<script src=“/static/autosave/js/
autosave.js”>
The problem
<!-- hashed-assets.html -->
<script src=“/static/admin/js/
collapse.min.c1a27df1b997.js”>
<script src=“/admin/editorial/
article/2/autosave_variables.js">
<script src=“/static/autosave/js/
autosave.js?v=2”>
That’s not all
That’s not all
That’s not all
That’s not all
Manifests for artefacts
class LocalManifestMixin(ManifestFilesMixin):
_local_storage = None
def __init__(self, *args, **kwargs):
super(LocalManifestMixin, self).__init__(*args, **kwargs)
self._local_storage = FileSystemStorage()
def read_manifest(self):
try:
with self._local_storage.open(self.manifest_name) as manifest:
return manifest.read().decode('utf-8')
except IOError:
return None
def save_manifest(self):
payload = {
'paths': self.hashed_files,
'version': self.manifest_version,
}
if self._local_storage.exists(self.manifest_name):
self._local_storage.delete(self.manifest_name)
contents = json.dumps(payload).encode('utf-8')
self._local_storage._save(
self.manifest_name, ContentFile(contents)
)
• #18929 CachedFilesMixin is not compatible with S3BotoStorage
• #19528 CachedFilesMixin does not rewrite rules for css

selector with path
• #19670 CachedFilesMixin Doesn't Limit Substitutions to Extension Matches
• #20620 CachedFileMixin.post_process breaks when cache size is exceeded
• #21080 collectstatic post-processing fails for references inside comments
• #22353 CachedStaticFilesMixin lags in updating hashed names of other static files
referenced in CSS
• #22972 HashedFilesMixin.patterns should limit URL matches to their respective filetypes
• #24243 Allow HashedFilesMixin to handle file name fragments
• #24452 Staticfiles backends using HashedFilesMixin don't update CSS files' hash
when referenced media changes
• #25283 ManifestStaticFilesStorage does not works in edge cases while

importing url font-face with IE hack
Some options for 3PA
• Fiat: All 3PAs use staticfiles
• Shim: all 3PAs use the admin approach, wrapping
it in their own taglib. Duplication!
• Bless: move staticfiles into core and make the
simple `load static` the same as `load staticfiles`
• Weakly bless staticfiles so `load static` behaves
like the admin, and the admin static stuff goes
away, and everyone just uses `load static`
Form media
Hurtful assets
Widgets, Forms, Admin
• Widgets might have specific assets to render
properly: typically CSS & JS
• Forms might have specific assets to render properly,
too. They’re made out of widgets and some other bits,
so they use the same system
• Then individual admin screens (ModelAdmin) might
have specific assets as well; they have Forms which
have Widgets
• Amazingly this hasn’t escaped into View
This is a good thing
from django.contrib import admin
from django.contrib.staticfiles.templatetags.staticfiles
import static
class ArticleAdmin(admin.ModelAdmin):
# ...
class Media:
js = [
'//tinymce.cachefly.net/4.1/tinymce.min.js',
static('js/tinymce_setup.js'),
]
This isn’t a good thing
from django.contrib.staticfiles.templatetags.staticfiles
import static
from django.contrib.admin.templatetags.admin_static
import static
• #9357 Unable to subclass form Media class
• #12264 calendar.js depends on jsi18n but date widgets using

it do not specify as required media
• #12265 Media (js/css) collection strategy in Forms has no order dependence
concept
• #13978 Allow inline js/css in forms.Media
• #18455 Added hooks to Media for staticfiles app
• #21221 Widgets and Admin's Media should use the configured staticfiles
storage to create the right path to a file
• #21318 Clarify the ordering of the various Media classes
• #21987 Allow Media objects to have their own MEDIA_TYPES
• #22298 Rename Media to Static
Some options
• Fiat: all 3PAs use staticfiles explicitly
• Shim: all 3PAs use the admin approach explicitly
• Bless: move staticfiles into core;
Media.absolute_path uses its storage
backend
• Weakly bless staticfiles, ie
Media.absolute_path uses the admin trick
This world’s a mess anyway
• no convenient API to get (CSS, JS) media
• can’t dedupe between forms if you have many
on one page
This world’s a mess anyway
• no convenient API to get (CSS, JS) media
• can’t dedupe between forms if you have many
on one page
• some things are global, eg jQuery, and can’t
easily dedupe between a widget and a site-wide
library
• to say nothing of different versions
Asset pipelines
What? Why?
• compilation
What? Why?
• compilation
• concatenation
What? Why?
• compilation
• concatenation or linking/encapsulation
What? Why?
• compilation
• concatenation or linking/encapsulation
• minification
What? Why?
• compilation
• concatenation or linking/encapsulation
• minification
• hashing and caching
Writing the HTML
<!-- rendered.html -->
<script type='text/javascript'
src='site.min.48fb66c7.js'>
<link rel='stylesheet' type='text/
css' href=‘site.min.29557b4f.css'>
Focus on targets
<!-- external-syntax.html -->
<script type='text/javascript' 

src='{% static "site.js" %}'>
<link rel='stylesheet'

type=‘text/css'
href='{% static "site.css" %}'>
Focus on sources
<!-- internal-syntax-1.html -->
<script type='text/javascript' src='menu.js'>
<script type='text/javascript' src='index.js'>
<link rel='stylesheet' type='text/css' href='nav.css'>
<link rel='stylesheet' type='text/css' href='footer.css'>
<link rel='stylesheet' type='text/css' href='index.css'>
<!-- internal-syntax-2.html -->
{% asset js 'menu.js' %}
{% asset js 'index.js' %}
{% asset css 'nav.css' %}
{% asset css 'footer.css' %}
{% asset css 'index.css' %}
Some asset pipelines
Rails / Sprocket
<%= stylesheet_link_tag
"application", media: "all" %>
<%= javascript_include_tag
"application" %>
Rails / Sprocket
//= require home
//= require moovinator
//= require slider
//= require phonebox
Rails / Sprocket
.class {
background-image: url(
<%= asset_path 'image.png' %>
)
}
Rails / Sprocket
rake assets:precompile
Rails / Sprocket
rake assets:clean
Sprocket clones
• asset-pipeline (Express/node.js)
• sails (node.js)
• grails asset pipeline (Groovy)
• Pipe (PHP)
node.js
• express-cdn
• Broccoli
• Sigh
• gulp
• Webpack
gulp (node.js)
var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var rev = require('gulp-rev');
gulp.task('default', ['compile-scss']);
gulp.task('compile-scss', function() {
gulp.src('source/stylesheets/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass(
{indentedSyntax: false, errLogToConsole: true }
))
.pipe(sourcemaps.write())
.pipe(rev())
.pipe(gulp.dest('static'));
});
gulp (node.js)
var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var rev = require('gulp-rev');
gulp.task('default', ['compile-scss']);
gulp.task('compile-scss', function() {
gulp.src('source/stylesheets/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass(
{indentedSyntax: false, errLogToConsole: true }
))
.pipe(sourcemaps.write())
.pipe(rev())
.pipe(gulp.dest('static'))
.pipe(rev.manifest())
.pipe(gulp.dest('static'));
});
Django options
• Plain django (external pipeline + staticfiles)
• django-compressor
• django-pipeline
Plain Django
• Pipeline external to Django (use what you want)
• Hashes computed by staticfiles
• Sourcemap support is fiddly if you want hashes
django-compressor
• Integrated pipeline, supports precompilers &c
• Source files listed in templates
• Integrated hashing
• Can be used with staticfiles, but feels awkward
• Can support sourcemaps, via a plugin
django-pipeline
• Internal pipeline, supports precompilers &c
• Source to output mapping in Django settings
• Integrates with staticfiles better than compressor
• Hashing via staticfiles
• Doesn’t support sourcemaps directly
Django + webpack
• webpack-bundle-tracker + django-webpack-
loader (Owais Lone 2015)
• Pipeline run by Webpack, emits a mapping file
• Template tag to resolve the bundle name to a
URL relative to STATIC_ROOT
Django options
• django-compressor: fixed pipeline
• django-pipelines: fixed pipeline (+ config woes)
• staticfiles: doesn’t get hashes right
• webpack-loader: isn’t generic
The future?
• pipeline builds named bundles into output files
• pipeline writes manifest.json: a mapping of
bundle name to output filename
• staticfiles storage reads in manifest.json on boot
• templates refer to the bundle name
• useful for staticfiles to be able to list static
directories (eg for node pipeline search paths)
Third-party apps
• can’t cooperate with your project’s pipeline
• don’t want to force a dependency on a pipeline
• so must precompile into files in your sdist
• possibly for staticfiles to sweep up (but we’ve
discussed this bit before)
What next?
What next?
• bless or semi-bless staticfiles?
• deprecate CachedStaticFilesStorage?
• document the boundaries of our hashing?
• rename? kill? expand? form.Media
• asset management / document external pipelines
• fix some bugs ;-)
• #9433 File locking broken on AFP mounts
• #17686 file.save crashes on unicode filename
• #18233 file_move_safe overwrites destination file
• #18655 Media files should be served using file
storage API
• #22961 StaticFilesHandler should not run
middleware on 404
😨🐉
• Durbed (durbed.deviantart.com) under CC By-
SA 3.0
• “Happy New Year from Hell Creek”
• “Primal feathers”
James Aylett
@jaylett

More Related Content

What's hot

Writing and Sharing Great Modules with the Puppet Forge
Writing and Sharing Great Modules with the Puppet ForgeWriting and Sharing Great Modules with the Puppet Forge
Writing and Sharing Great Modules with the Puppet Forge
Puppet
 
DSpace 4.2 XMLUI Theming
DSpace 4.2 XMLUI ThemingDSpace 4.2 XMLUI Theming
DSpace 4.2 XMLUI Theming
DuraSpace
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
Erik Hatcher
 
Generators: The Final Frontier
Generators: The Final FrontierGenerators: The Final Frontier
Generators: The Final Frontier
David Beazley (Dabeaz LLC)
 
Drupal 8 Configuration Management
Drupal 8 Configuration ManagementDrupal 8 Configuration Management
Drupal 8 Configuration Management
Philip Norton
 
DSpace 4.2 Transmission: Import/Export
DSpace 4.2 Transmission: Import/ExportDSpace 4.2 Transmission: Import/Export
DSpace 4.2 Transmission: Import/Export
DuraSpace
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
Erik Hatcher
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
Adam Tomat
 
Tutorial on developing a Solr search component plugin
Tutorial on developing a Solr search component pluginTutorial on developing a Solr search component plugin
Tutorial on developing a Solr search component plugin
searchbox-com
 
Webinar - Managing Files with Puppet
Webinar - Managing Files with PuppetWebinar - Managing Files with Puppet
Webinar - Managing Files with Puppet
OlinData
 
code4lib 2011 preconference: What's New in Solr (since 1.4.1)
code4lib 2011 preconference: What's New in Solr (since 1.4.1)code4lib 2011 preconference: What's New in Solr (since 1.4.1)
code4lib 2011 preconference: What's New in Solr (since 1.4.1)
Erik Hatcher
 
Enterprise Search Solution: Apache SOLR. What's available and why it's so cool
Enterprise Search Solution: Apache SOLR. What's available and why it's so coolEnterprise Search Solution: Apache SOLR. What's available and why it's so cool
Enterprise Search Solution: Apache SOLR. What's available and why it's so cool
Ecommerce Solution Provider SysIQ
 
Using Apache Solr
Using Apache SolrUsing Apache Solr
Using Apache Solr
pittaya
 
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Nuvole
 
Parsing strange v3
Parsing strange v3Parsing strange v3
Parsing strange v3
Hal Stern
 
Webinar - Windows Application Management with Puppet
Webinar - Windows Application Management with PuppetWebinar - Windows Application Management with Puppet
Webinar - Windows Application Management with Puppet
OlinData
 
Parsing strange v4
Parsing strange v4Parsing strange v4
Parsing strange v4
Hal Stern
 
Lucene's Latest (for Libraries)
Lucene's Latest (for Libraries)Lucene's Latest (for Libraries)
Lucene's Latest (for Libraries)
Erik Hatcher
 
Solr 6 Feature Preview
Solr 6 Feature PreviewSolr 6 Feature Preview
Solr 6 Feature Preview
Yonik Seeley
 
Solr Recipes Workshop
Solr Recipes WorkshopSolr Recipes Workshop
Solr Recipes Workshop
Erik Hatcher
 

What's hot (20)

Writing and Sharing Great Modules with the Puppet Forge
Writing and Sharing Great Modules with the Puppet ForgeWriting and Sharing Great Modules with the Puppet Forge
Writing and Sharing Great Modules with the Puppet Forge
 
DSpace 4.2 XMLUI Theming
DSpace 4.2 XMLUI ThemingDSpace 4.2 XMLUI Theming
DSpace 4.2 XMLUI Theming
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
 
Generators: The Final Frontier
Generators: The Final FrontierGenerators: The Final Frontier
Generators: The Final Frontier
 
Drupal 8 Configuration Management
Drupal 8 Configuration ManagementDrupal 8 Configuration Management
Drupal 8 Configuration Management
 
DSpace 4.2 Transmission: Import/Export
DSpace 4.2 Transmission: Import/ExportDSpace 4.2 Transmission: Import/Export
DSpace 4.2 Transmission: Import/Export
 
Rapid Prototyping with Solr
Rapid Prototyping with SolrRapid Prototyping with Solr
Rapid Prototyping with Solr
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
 
Tutorial on developing a Solr search component plugin
Tutorial on developing a Solr search component pluginTutorial on developing a Solr search component plugin
Tutorial on developing a Solr search component plugin
 
Webinar - Managing Files with Puppet
Webinar - Managing Files with PuppetWebinar - Managing Files with Puppet
Webinar - Managing Files with Puppet
 
code4lib 2011 preconference: What's New in Solr (since 1.4.1)
code4lib 2011 preconference: What's New in Solr (since 1.4.1)code4lib 2011 preconference: What's New in Solr (since 1.4.1)
code4lib 2011 preconference: What's New in Solr (since 1.4.1)
 
Enterprise Search Solution: Apache SOLR. What's available and why it's so cool
Enterprise Search Solution: Apache SOLR. What's available and why it's so coolEnterprise Search Solution: Apache SOLR. What's available and why it's so cool
Enterprise Search Solution: Apache SOLR. What's available and why it's so cool
 
Using Apache Solr
Using Apache SolrUsing Apache Solr
Using Apache Solr
 
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
Configuration Management in Drupal 8: A preview (DrupalDays Milano 2014)
 
Parsing strange v3
Parsing strange v3Parsing strange v3
Parsing strange v3
 
Webinar - Windows Application Management with Puppet
Webinar - Windows Application Management with PuppetWebinar - Windows Application Management with Puppet
Webinar - Windows Application Management with Puppet
 
Parsing strange v4
Parsing strange v4Parsing strange v4
Parsing strange v4
 
Lucene's Latest (for Libraries)
Lucene's Latest (for Libraries)Lucene's Latest (for Libraries)
Lucene's Latest (for Libraries)
 
Solr 6 Feature Preview
Solr 6 Feature PreviewSolr 6 Feature Preview
Solr 6 Feature Preview
 
Solr Recipes Workshop
Solr Recipes WorkshopSolr Recipes Workshop
Solr Recipes Workshop
 

Similar to Django Files — A Short Talk (slides only)

Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
Data Replication Options in AWS (ARC302) | AWS re:Invent 2013Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
Amazon Web Services
 
Solr Application Development Tutorial
Solr Application Development TutorialSolr Application Development Tutorial
Solr Application Development Tutorial
Erik Hatcher
 
Using Document Databases with TYPO3 Flow
Using Document Databases with TYPO3 FlowUsing Document Databases with TYPO3 Flow
Using Document Databases with TYPO3 Flow
Karsten Dambekalns
 
AmazonS3 & Rails
AmazonS3 & RailsAmazonS3 & Rails
AmazonS3 & Rails
_martinS_
 
Hadoop_File_Formats_and_Data_Ingestion.pptx
Hadoop_File_Formats_and_Data_Ingestion.pptxHadoop_File_Formats_and_Data_Ingestion.pptx
Hadoop_File_Formats_and_Data_Ingestion.pptx
ShashankSahu34
 
Javase7 1641812
Javase7 1641812Javase7 1641812
Javase7 1641812
Vinay H G
 
Apache Hive, data segmentation and bucketing
Apache Hive, data segmentation and bucketingApache Hive, data segmentation and bucketing
Apache Hive, data segmentation and bucketing
earnwithme2522
 
Android Data Persistence
Android Data PersistenceAndroid Data Persistence
Android Data Persistence
Jussi Pohjolainen
 
S3 & Glacier - The only backup solution you'll ever need
S3 & Glacier - The only backup solution you'll ever needS3 & Glacier - The only backup solution you'll ever need
S3 & Glacier - The only backup solution you'll ever need
Matthew Boeckman
 
Optimizing Big Data to run in the Public Cloud
Optimizing Big Data to run in the Public CloudOptimizing Big Data to run in the Public Cloud
Optimizing Big Data to run in the Public Cloud
Qubole
 
Super hybrid2016 tdc
Super hybrid2016 tdcSuper hybrid2016 tdc
Super hybrid2016 tdc
Murilo Miranda
 
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
buildacloud
 
Open writing-cloud-collab
Open writing-cloud-collabOpen writing-cloud-collab
Open writing-cloud-collab
Karen Vuong
 
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
Peter Keane
 
12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat
linoj
 
REST in Piece - Administration of an Oracle Cluster/Database using REST
REST in Piece - Administration of an Oracle Cluster/Database using RESTREST in Piece - Administration of an Oracle Cluster/Database using REST
REST in Piece - Administration of an Oracle Cluster/Database using REST
Christian Gohmann
 
Corporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbaiCorporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbai
Unmesh Baile
 
Corporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbaiCorporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbai
Unmesh Baile
 
Information Retrieval - Data Science Bootcamp
Information Retrieval - Data Science BootcampInformation Retrieval - Data Science Bootcamp
Information Retrieval - Data Science Bootcamp
Kais Hassan, PhD
 
Drupal 8 configuration management
Drupal 8 configuration managementDrupal 8 configuration management
Drupal 8 configuration management
Alexander Tkachev
 

Similar to Django Files — A Short Talk (slides only) (20)

Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
Data Replication Options in AWS (ARC302) | AWS re:Invent 2013Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
Data Replication Options in AWS (ARC302) | AWS re:Invent 2013
 
Solr Application Development Tutorial
Solr Application Development TutorialSolr Application Development Tutorial
Solr Application Development Tutorial
 
Using Document Databases with TYPO3 Flow
Using Document Databases with TYPO3 FlowUsing Document Databases with TYPO3 Flow
Using Document Databases with TYPO3 Flow
 
AmazonS3 & Rails
AmazonS3 & RailsAmazonS3 & Rails
AmazonS3 & Rails
 
Hadoop_File_Formats_and_Data_Ingestion.pptx
Hadoop_File_Formats_and_Data_Ingestion.pptxHadoop_File_Formats_and_Data_Ingestion.pptx
Hadoop_File_Formats_and_Data_Ingestion.pptx
 
Javase7 1641812
Javase7 1641812Javase7 1641812
Javase7 1641812
 
Apache Hive, data segmentation and bucketing
Apache Hive, data segmentation and bucketingApache Hive, data segmentation and bucketing
Apache Hive, data segmentation and bucketing
 
Android Data Persistence
Android Data PersistenceAndroid Data Persistence
Android Data Persistence
 
S3 & Glacier - The only backup solution you'll ever need
S3 & Glacier - The only backup solution you'll ever needS3 & Glacier - The only backup solution you'll ever need
S3 & Glacier - The only backup solution you'll ever need
 
Optimizing Big Data to run in the Public Cloud
Optimizing Big Data to run in the Public CloudOptimizing Big Data to run in the Public Cloud
Optimizing Big Data to run in the Public Cloud
 
Super hybrid2016 tdc
Super hybrid2016 tdcSuper hybrid2016 tdc
Super hybrid2016 tdc
 
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
Open Writing! Collaborative Authoring for CloudStack Documentation by Jessica...
 
Open writing-cloud-collab
Open writing-cloud-collabOpen writing-cloud-collab
Open writing-cloud-collab
 
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
The Role of Atom/AtomPub in Digital Archive Services at The University of Tex...
 
12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat
 
REST in Piece - Administration of an Oracle Cluster/Database using REST
REST in Piece - Administration of an Oracle Cluster/Database using RESTREST in Piece - Administration of an Oracle Cluster/Database using REST
REST in Piece - Administration of an Oracle Cluster/Database using REST
 
Corporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbaiCorporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbai
 
Corporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbaiCorporate-informatica-training-in-mumbai
Corporate-informatica-training-in-mumbai
 
Information Retrieval - Data Science Bootcamp
Information Retrieval - Data Science BootcampInformation Retrieval - Data Science Bootcamp
Information Retrieval - Data Science Bootcamp
 
Drupal 8 configuration management
Drupal 8 configuration managementDrupal 8 configuration management
Drupal 8 configuration management
 

More from James Aylett

Git, from the beginning
Git, from the beginningGit, from the beginning
Git, from the beginning
James Aylett
 
IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?
James Aylett
 
Beyond blockers
Beyond blockersBeyond blockers
Beyond blockers
James Aylett
 
Tree surgery
Tree surgeryTree surgery
Tree surgery
James Aylett
 
On committing well
On committing wellOn committing well
On committing well
James Aylett
 
/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw
James Aylett
 
Accessible by Voice
Accessible by VoiceAccessible by Voice
Accessible by Voice
James Aylett
 
Spacelog: things we did right-ish
Spacelog: things we did right-ishSpacelog: things we did right-ish
Spacelog: things we did right-ish
James Aylett
 
Web heresies
Web heresiesWeb heresies
Web heresies
James Aylett
 
Five class-based views everyone has written by now
Five class-based views everyone has written by nowFive class-based views everyone has written by now
Five class-based views everyone has written by now
James Aylett
 

More from James Aylett (10)

Git, from the beginning
Git, from the beginningGit, from the beginning
Git, from the beginning
 
IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?IA Isn't New, or: What would Samuel Pepys' website look like?
IA Isn't New, or: What would Samuel Pepys' website look like?
 
Beyond blockers
Beyond blockersBeyond blockers
Beyond blockers
 
Tree surgery
Tree surgeryTree surgery
Tree surgery
 
On committing well
On committing wellOn committing well
On committing well
 
/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw/dev/fort: you can build it in a week @emw
/dev/fort: you can build it in a week @emw
 
Accessible by Voice
Accessible by VoiceAccessible by Voice
Accessible by Voice
 
Spacelog: things we did right-ish
Spacelog: things we did right-ishSpacelog: things we did right-ish
Spacelog: things we did right-ish
 
Web heresies
Web heresiesWeb heresies
Web heresies
 
Five class-based views everyone has written by now
Five class-based views everyone has written by nowFive class-based views everyone has written by now
Five class-based views everyone has written by now
 

Recently uploaded

Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
Grant Fritchey
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
Yara Milbes
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
Alberto Brandolini
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
Marcin Chrost
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
brainerhub1
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
kgyxske
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
aisafed42
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 

Recently uploaded (20)

Using Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query PerformanceUsing Query Store in Azure PostgreSQL to Understand Query Performance
Using Query Store in Azure PostgreSQL to Understand Query Performance
 
The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024The Rising Future of CPaaS in the Middle East 2024
The Rising Future of CPaaS in the Middle East 2024
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdfBaha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
Baha Majid WCA4Z IBM Z Customer Council Boston June 2024.pdf
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 

Django Files — A Short Talk (slides only)

  • 2. Files in an exciting adventure with dinosaurs
  • 3. Files in an exciting adventure with dinosaurs
  • 5. TZ=CET ls -ltr talk/ -rwxr--r-- 1 jaylett django 6 6 Nov 14:01 Files -rwxr--r-- 1 jaylett django 5 6 Nov 14:02 Files and HTTP -rwxr--r-- 1 jaylett django 15 6 Nov 14:04 Files in the ORM -rwxr--r-- 1 jaylett django 13 6 Nov 14:08 Storage backends -rwxr--r-- 1 jaylett django 25 6 Nov 14:20 Static files -rwxr--r-- 1 jaylett django 8 6 Nov 14:35 Form media -rwxr--r-- 1 jaylett django 29 6 Nov 14:40 Asset pipelines -rwxr--r-- 1 jaylett django 6 6 Nov 14:55 What next?
  • 10. The File family • File — or ImageFile, if it might be an image • ContentFile / SimpleUploadedFile in tests • which have a different parameter order
  • 11. • #10541 cannot save file from a pipe
  • 13. UploadedFile • “behaves somewhat like a file object” • temporary file and memory variants • custom upload handlers
  • 14. forms.FileField # forms-filefield.py class FileForm(forms.Form): uploaded = forms.FileField() def upload(request): if request.method == 'POST': form = FileForm(request.POST, request.FILES) if form.is_valid(): request.FILES['uploaded'] # do something! return HttpResponseRedirect('/next/') else: form = FileForm() return render_to_response( 'upload.html', {'form': form}, )
  • 16. • #15879 multipart/form-data filename=""
 not handled as file • #17955 Uploading a file without using django forms • #18150 Uploading a file ending with a
 backslash fails • #20034 Upload handlers provide no way to retrieve previously parsed POST variables • #21588 "Modifying upload handlers on the fly" documentation doesn't replicate internal magic
  • 18. Files in the ORM # orm-file.py class Wub(models.Model): infosheet = models.FileField() >>> w = Wub(infosheet="relative/to/media/root.pdf") >>> print w.infosheet.url https://media.root/relative/to/media/root.pdf >>> w.infosheet = ContentFile("A boring bit of text", “file.txt") >>> print w.infosheet.url https://media.root/file.txt
  • 19. • #5619 FileField and ImageField return the wrong path/url
 before calling save_FOO_file() • #10244 FileFields can't be set to NULL in the db • #13809 FileField open method is only accepting 'rb' modes • #14039 FileField special-casing breaks MultiValueField including a FileField • #13327 FileField/ImageField accessor methods throw unnecessary exceptions when they are blank or null. • #17224 determine and document the use of default option in context of FileField • #25547 refresh_from_db leaves FieldFile with reference to db_instance
  • 20. Files in the ORM # orm-file.py class Wub(models.Model): infosheet = models.FileField() >>> w = Wub(infosheet="relative/to/media/root.pdf") >>> print w.infosheet.url http://media.root/relative/to/media/root.pdf >>> w.infosheet = ContentFile("A boring bit of text", “file.txt") >>> print w.infosheet.url http://media.root/file.txt >>> w.infosheet = None >>> print w.infosheet.url
  • 21. Files in the ORM # orm-file.py class Wub(models.Model): infosheet = models.FileField() >>> w = Wub(infosheet="relative/to/media/root.pdf") >>> print w.infosheet.url http://media.root/relative/to/media/root.pdf >>> w.infosheet = ContentFile("A boring bit of text", “file.txt") >>> print w.infosheet.url http://media.root/file.txt >>> w.infosheet = None >>> print w.infosheet.url >>> print type(w.infosheet) FieldFile <class 'django.db.models.fields.files.FieldFile'>
  • 22. FieldFile • magical autoconversion for anything (within reason) • this happens using FileDescriptor classes which, well, let’s just ignore that
  • 23. FileField # orm-fieldfile.py class Wub(models.Model): infosheet = models.FileField() >>> w = Wub(infosheet="relative/to/media/ root.pdf") >>> w.infosheet = None >>> w.infosheet == None True >>> w.infosheet is None False
  • 24. • #18283 FileField should not reuse FieldFiles
  • 25. In ModelForms # modelforms-filefield.py class Wub(models.Model): infosheet = models.FileField() class WubCreate(CreateView): model = Wub fields = ['infosheet']
  • 26. ImageField # orm-imagefile.py class Wub(models.Model): infosheet = models.FileField() photo = models.ImageField() >>> w = Wub(infosheet="relative/to/media/ root.pdf", photo="relative/to/media/ root.png") >>> w.photo.width, w.photo.height (480, 200)
  • 27. • #15817 ImageField having
 [width|height]_field set sytematically compute
 the image dimensions in ModelForm validation process • #18543 Non image file can be saved to ImageField • #19215 ImageField's “Currently” and “Clear” Sometimes Don't Appear • #21548 Add the ability to limit file extensions for ImageField and FileField
  • 30. ImageField # orm-imagefile-proxies.py class Wub(models.Model): infosheet = models.FileField() photo = models.ImageField(width_field='photo_width', height_field='photo_height') photo_width = models.PositiveIntegerField(blank=True) photo_height = models.PositiveIntegerField(blank=True) >>> w = Wub(infosheet="relative/to/media/root.pdf", photo="relative/to/media/root.png") >>> w.photo.width, w.photo.height (480, 200) >>> w.photo_width, w.photo_height (480, 200)
  • 31. • #8307 ImageFile use of width_field and height_field is slow with remote storage backends • #13750 ImageField accessing height or width and then data results in "I/O operation on closed file”
  • 33. Storing files • Stored in MEDIA_ROOT • Served from MEDIA_URL • Uses FileSystemStorage…by default
  • 35. What can Storage do? • oriented around files, rather than a general FS API • open / save / delete / exists / size / path / url • make an available name, ie one that doesn’t clash • modified, created, accessed times • … also listdir
  • 36. Choosing storage # configuring-storage-settings.py DEFAULT_FILE_STORAGE = 'dotted.path.Class' MEDIA_ROOT = '/my-root' MEDIA_URL = 'https://media.root/' class MyStorage(FileSystemStorage): def __init__(self, **kwargs): kwargs.setdefault( 'location', '/my-root' ) kwargs.setdefault( 'base_url', 'https://media.root/' ) return super( MyStorage, self ).__init__(**kwargs)
  • 37. Choosing storage # models.py from mystorage import BetterStorage storage_instance = BetterStorage() class MyModel(models.Model): upload = models.FileField( storage=storage_instance )
  • 38. • #9586 Shall upload_to return an urlencoded
 string or not? • #12157 FileSystemStorage does file I/O inefficiently, despite providing options to permit larger blocksizes • #15799 Document what exception should be raised when trying to open non-existent file • #21602 FileSystemStorage._save() Should Save to a Temporary Filename and Rename to Attempt to be Atomic • #23759 Storage.get_available_name should preserve all file extensions, not just the first one • #23832 Storage API should provide a timezone aware approach
  • 39. Reasons to override • Model fields with different options • Different storage engine entirely
  • 40. Protected storage FSS = FileSystemStorage pstore = FSS( location=‘/protected’, base_url="/p/", ) urlpatterns += patterns( url( r'^p/(?P<path>.*)$', protected, ), ) class Profile(models.Model): resume = FileField( null=True, blank=True, storage=pstore, ) @login_required def protected(request, path): f = pstore.open(path) return HttpResponse( f.chunks() )
  • 41. S3BotoStorage • One of many in django-storages-redux • Millions of options, somewhat undocumented • configure with AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_STORAGE_BUCKET_NAME • defaults for the rest mostly sane
  • 42. Fun with S3Boto AWS_S3_CUSTOM_DOMAIN='cdn.eg.com' AWS_HEADERS={ 'Cache-Control': 'max-age=31536000' } # a year or so AWS_PRELOAD_METADATA=True
  • 43. Protected S3 storage protected_storage = S3BotoStorage( acl='private', querystring_auth=True, querystring_expire=600, # 10 minutes, try to ensure people # won’t / can't share ) model.field.url # works as expected
  • 44. Code that uses storage • Please test on both Windows and Linux/Unix • Please test with something remote like S3Boto • Please write your own tests to work with different storage backends
  • 47. How it works <!-- source.html --> {% load static %} <img src='{% static "asset/path.png" %}' width='200' height='100' alt=''> <!-- out.html --> <img src='https://static.root/asset/path.png' width='200' height='100' alt=‘'>
  • 50. • #24336 static server should skip for protocol- relative STATIC_URL • #25022 collectstatic create self-referential symlink
  • 53. • #23563 Make `staticfiles_storage` a public API • #25484 static template tag outputs invalid HTML if storage class's url() returns a URI with '&' characters.
  • 54. I make it sound bad Really, it’s not
  • 55. Still a moderately bad time
  • 56. Still a moderately bad time
  • 60. Cached (1.4) / Manifest (1.7) • Cache uses the main cache, or a dedicated one • Manifest writes a JSON manifest file to the configured storage backend
  • 61. The problem <!-- hashed-assets.html --> <script src=“/static/admin/js/ collapse.min.c1a27df1b997.js”> <script src=“/admin/editorial/ article/2/autosave_variables.js"> <script src=“/static/autosave/js/ autosave.js”>
  • 62. The problem <!-- hashed-assets.html --> <script src=“/static/admin/js/ collapse.min.c1a27df1b997.js”> <script src=“/admin/editorial/ article/2/autosave_variables.js"> <script src=“/static/autosave/js/ autosave.js?v=2”>
  • 67. Manifests for artefacts class LocalManifestMixin(ManifestFilesMixin): _local_storage = None def __init__(self, *args, **kwargs): super(LocalManifestMixin, self).__init__(*args, **kwargs) self._local_storage = FileSystemStorage() def read_manifest(self): try: with self._local_storage.open(self.manifest_name) as manifest: return manifest.read().decode('utf-8') except IOError: return None def save_manifest(self): payload = { 'paths': self.hashed_files, 'version': self.manifest_version, } if self._local_storage.exists(self.manifest_name): self._local_storage.delete(self.manifest_name) contents = json.dumps(payload).encode('utf-8') self._local_storage._save( self.manifest_name, ContentFile(contents) )
  • 68. • #18929 CachedFilesMixin is not compatible with S3BotoStorage • #19528 CachedFilesMixin does not rewrite rules for css
 selector with path • #19670 CachedFilesMixin Doesn't Limit Substitutions to Extension Matches • #20620 CachedFileMixin.post_process breaks when cache size is exceeded • #21080 collectstatic post-processing fails for references inside comments • #22353 CachedStaticFilesMixin lags in updating hashed names of other static files referenced in CSS • #22972 HashedFilesMixin.patterns should limit URL matches to their respective filetypes • #24243 Allow HashedFilesMixin to handle file name fragments • #24452 Staticfiles backends using HashedFilesMixin don't update CSS files' hash when referenced media changes • #25283 ManifestStaticFilesStorage does not works in edge cases while
 importing url font-face with IE hack
  • 69. Some options for 3PA • Fiat: All 3PAs use staticfiles • Shim: all 3PAs use the admin approach, wrapping it in their own taglib. Duplication! • Bless: move staticfiles into core and make the simple `load static` the same as `load staticfiles` • Weakly bless staticfiles so `load static` behaves like the admin, and the admin static stuff goes away, and everyone just uses `load static`
  • 71. Widgets, Forms, Admin • Widgets might have specific assets to render properly: typically CSS & JS • Forms might have specific assets to render properly, too. They’re made out of widgets and some other bits, so they use the same system • Then individual admin screens (ModelAdmin) might have specific assets as well; they have Forms which have Widgets • Amazingly this hasn’t escaped into View
  • 72. This is a good thing from django.contrib import admin from django.contrib.staticfiles.templatetags.staticfiles import static class ArticleAdmin(admin.ModelAdmin): # ... class Media: js = [ '//tinymce.cachefly.net/4.1/tinymce.min.js', static('js/tinymce_setup.js'), ]
  • 73. This isn’t a good thing from django.contrib.staticfiles.templatetags.staticfiles import static from django.contrib.admin.templatetags.admin_static import static
  • 74. • #9357 Unable to subclass form Media class • #12264 calendar.js depends on jsi18n but date widgets using
 it do not specify as required media • #12265 Media (js/css) collection strategy in Forms has no order dependence concept • #13978 Allow inline js/css in forms.Media • #18455 Added hooks to Media for staticfiles app • #21221 Widgets and Admin's Media should use the configured staticfiles storage to create the right path to a file • #21318 Clarify the ordering of the various Media classes • #21987 Allow Media objects to have their own MEDIA_TYPES • #22298 Rename Media to Static
  • 75. Some options • Fiat: all 3PAs use staticfiles explicitly • Shim: all 3PAs use the admin approach explicitly • Bless: move staticfiles into core; Media.absolute_path uses its storage backend • Weakly bless staticfiles, ie Media.absolute_path uses the admin trick
  • 76. This world’s a mess anyway • no convenient API to get (CSS, JS) media • can’t dedupe between forms if you have many on one page
  • 77. This world’s a mess anyway • no convenient API to get (CSS, JS) media • can’t dedupe between forms if you have many on one page • some things are global, eg jQuery, and can’t easily dedupe between a widget and a site-wide library • to say nothing of different versions
  • 81. What? Why? • compilation • concatenation or linking/encapsulation
  • 82. What? Why? • compilation • concatenation or linking/encapsulation • minification
  • 83. What? Why? • compilation • concatenation or linking/encapsulation • minification • hashing and caching
  • 84. Writing the HTML <!-- rendered.html --> <script type='text/javascript' src='site.min.48fb66c7.js'> <link rel='stylesheet' type='text/ css' href=‘site.min.29557b4f.css'>
  • 85. Focus on targets <!-- external-syntax.html --> <script type='text/javascript' 
 src='{% static "site.js" %}'> <link rel='stylesheet'
 type=‘text/css' href='{% static "site.css" %}'>
  • 86. Focus on sources <!-- internal-syntax-1.html --> <script type='text/javascript' src='menu.js'> <script type='text/javascript' src='index.js'> <link rel='stylesheet' type='text/css' href='nav.css'> <link rel='stylesheet' type='text/css' href='footer.css'> <link rel='stylesheet' type='text/css' href='index.css'> <!-- internal-syntax-2.html --> {% asset js 'menu.js' %} {% asset js 'index.js' %} {% asset css 'nav.css' %} {% asset css 'footer.css' %} {% asset css 'index.css' %}
  • 88. Rails / Sprocket <%= stylesheet_link_tag "application", media: "all" %> <%= javascript_include_tag "application" %>
  • 89. Rails / Sprocket //= require home //= require moovinator //= require slider //= require phonebox
  • 90. Rails / Sprocket .class { background-image: url( <%= asset_path 'image.png' %> ) }
  • 91. Rails / Sprocket rake assets:precompile
  • 92. Rails / Sprocket rake assets:clean
  • 93. Sprocket clones • asset-pipeline (Express/node.js) • sails (node.js) • grails asset pipeline (Groovy) • Pipe (PHP)
  • 94. node.js • express-cdn • Broccoli • Sigh • gulp • Webpack
  • 95. gulp (node.js) var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var rev = require('gulp-rev'); gulp.task('default', ['compile-scss']); gulp.task('compile-scss', function() { gulp.src('source/stylesheets/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass( {indentedSyntax: false, errLogToConsole: true } )) .pipe(sourcemaps.write()) .pipe(rev()) .pipe(gulp.dest('static')); });
  • 96. gulp (node.js) var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var rev = require('gulp-rev'); gulp.task('default', ['compile-scss']); gulp.task('compile-scss', function() { gulp.src('source/stylesheets/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass( {indentedSyntax: false, errLogToConsole: true } )) .pipe(sourcemaps.write()) .pipe(rev()) .pipe(gulp.dest('static')) .pipe(rev.manifest()) .pipe(gulp.dest('static')); });
  • 97. Django options • Plain django (external pipeline + staticfiles) • django-compressor • django-pipeline
  • 98. Plain Django • Pipeline external to Django (use what you want) • Hashes computed by staticfiles • Sourcemap support is fiddly if you want hashes
  • 99. django-compressor • Integrated pipeline, supports precompilers &c • Source files listed in templates • Integrated hashing • Can be used with staticfiles, but feels awkward • Can support sourcemaps, via a plugin
  • 100. django-pipeline • Internal pipeline, supports precompilers &c • Source to output mapping in Django settings • Integrates with staticfiles better than compressor • Hashing via staticfiles • Doesn’t support sourcemaps directly
  • 101. Django + webpack • webpack-bundle-tracker + django-webpack- loader (Owais Lone 2015) • Pipeline run by Webpack, emits a mapping file • Template tag to resolve the bundle name to a URL relative to STATIC_ROOT
  • 102. Django options • django-compressor: fixed pipeline • django-pipelines: fixed pipeline (+ config woes) • staticfiles: doesn’t get hashes right • webpack-loader: isn’t generic
  • 103. The future? • pipeline builds named bundles into output files • pipeline writes manifest.json: a mapping of bundle name to output filename • staticfiles storage reads in manifest.json on boot • templates refer to the bundle name • useful for staticfiles to be able to list static directories (eg for node pipeline search paths)
  • 104. Third-party apps • can’t cooperate with your project’s pipeline • don’t want to force a dependency on a pipeline • so must precompile into files in your sdist • possibly for staticfiles to sweep up (but we’ve discussed this bit before)
  • 106. What next? • bless or semi-bless staticfiles? • deprecate CachedStaticFilesStorage? • document the boundaries of our hashing? • rename? kill? expand? form.Media • asset management / document external pipelines • fix some bugs ;-)
  • 107. • #9433 File locking broken on AFP mounts • #17686 file.save crashes on unicode filename • #18233 file_move_safe overwrites destination file • #18655 Media files should be served using file storage API • #22961 StaticFilesHandler should not run middleware on 404
  • 108.
  • 109. 😨🐉 • Durbed (durbed.deviantart.com) under CC By- SA 3.0 • “Happy New Year from Hell Creek” • “Primal feathers”