Storing files¶
In OIOIOI we need some mechanism to exchange files with external judging
machines. We use Filetracker for it. It’s our custom module and lives in the
Git repository in lib/filetracker
.
Filetracker in Django¶
Most of the Django files docs still apply. The only difference is that we
use our custom model field and storage manager, as specified in settngs.py
:
DEFAULT_FILE_STORAGE = 'oioioi.filetracker.storage.FiletrackerStorage'
To store a field in a model, use code like this:
from django.db import models
from oioioi.filetracker.fields import FileField
class TestFileModel(models.Model):
file_field = FileField(upload_to='some/folder')
Frequently you don’t want all files from a single field occupy a single folder.
No one wants all input files for all tasks to be in a single folder. Therefore
in practice you usually pass a filename generator as upload_to
. You may do
it like this:
from djang.utils.text import get_valid_filename
import os.path
def make_test_filename(instance, filename):
# instance will be an instance of Test
# filename will be the name of the file uploaded by the user
# or passed programatically to instance.input_file.save()
return 'problems/%d/%s' % (instance.problem.id,
get_valid_filename(os.path.basename(filename)))
class Test(models.Model):
problem = models.ForeignKey('Problem', on_delete=models.CASCADE)
input_file = FileField(upload_to=make_test_filename)
To store an existing file, write something like this:
from django.core.files import File
my_model.file_field = File(open('/etc/passwd', 'rb'), name='myfile.txt')
# or: my_model.file_field.save('myfile.txt', File(open('/etc/passwd', 'rb')))
To store a string variable:
from django.core.files import ContentFile
my_model.file_field = ContentFile('content of file', name='myfile.txt')
# or: my_model.file_field.save('myfile.txt', ContentFile('content of file'))
To assign a file, which is already in Filetracker:
from oioioi.filetracker.utils import filetracker_to_django_file
my_model.file_field = filetracker_to_django_file('/path/in/filetracker/to/myfile.txt')
Note
This is assignment, so any output of upload_to
will be ignored.
Accessing Filetracker client¶
To obtain the Filetracker client class instance, use
oioioi.filetracker.client.get_client()
. Our Django Filetracker storage
backend uses this function as well.
- oioioi.filetracker.client.get_client()[source]¶
Constructs a Filetracker client.
Needs a
FILETRACKER_CLIENT_FACTORY
entry insettings.py
, which should contain a dotted name of a function which returns afiletracker.client.Client
instance. A good candidate isremote_storage_factory()
.The constructed client is cached.
- oioioi.filetracker.client.remote_storage_factory()[source]¶
A filetracker factory which creates a client that uses the remote server at
settings.FILETRACKER_URL
and a foldersettings.FILETRACKER_CACHE_ROOT
as a cache directory.
Indeed, in settings.py
you will find:
FILETRACKER_CLIENT_FACTORY = 'oioioi.filetracker.client.remote_storage_factory'
Testing with files¶
Database fixtures allow to store database entities ready for use in tests.
Our FileField
is tweaked to also serialize its content, and deserialize
automatically when fixtures are loaded.