doc/book/en/tutorials/advanced/part03_bfss.rst
branchstable
changeset 6876 4b0b9d8207c5
child 6923 327443ec7120
equal deleted inserted replaced
6875:a166b51d13f8 6876:4b0b9d8207c5
       
     1 Storing images on the file-system
       
     2 ---------------------------------
       
     3 
       
     4 Step 1: configuring the BytesFileSystem storage
       
     5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
     6 
       
     7 To avoid cluttering my database, and to ease file manipulation, I don't want
       
     8 them to be stored in the database. I want to be able create File/Image entities
       
     9 for some files on the server file system, where those file will be accessed to
       
    10 get entities data. To do so I've to set a custom :class:`BytesFileSystemStorage` storage
       
    11 for the File/Image 'data' attribute, which hold the actual file's content.
       
    12 
       
    13 Since the function to register a custom storage needs to have a repository
       
    14 instance as first argument, we've to call it in a server startup hook. So I added
       
    15 in `cubes/sytweb/hooks.py` :
       
    16 
       
    17 .. sourcecode:: python
       
    18 
       
    19     from os import makedirs
       
    20     from os.path import join, exists
       
    21 
       
    22     from cubicweb.server import hook
       
    23     from cubicweb.server.sources import storage
       
    24 
       
    25     class ServerStartupHook(hook.Hook):
       
    26 	__regid__ = 'sytweb.serverstartup'
       
    27 	events = ('server_startup', 'server_maintenance')
       
    28 
       
    29 	def __call__(self):
       
    30 	    bfssdir = join(self.repo.config.appdatahome, 'bfss')
       
    31 	    if not exists(bfssdir):
       
    32 		makedirs(bfssdir)
       
    33 		print 'created', bfssdir
       
    34 	    storage = storages.BytesFileSystemStorage(bfssdir)
       
    35 	    set_attribute_storage(self.repo, 'File', 'data', storage)
       
    36 	    set_attribute_storage(self.repo, 'Image', 'data', storage)
       
    37 
       
    38 .. Note::
       
    39 
       
    40   * how we built the hook's registry identifier (_`_regid__`): you can introduce
       
    41     'namespaces' by using there python module like naming identifiers. This is
       
    42     especially import for hooks where you usually want a new custom hook, not
       
    43     overriding / specializing an existant one, but the concept may be applied to
       
    44     any application objects
       
    45 
       
    46   * we catch two events here: "server_startup" and "server_maintenance". The first
       
    47     is called on regular repository startup (eg, as a server), the other for
       
    48     maintenance task such as shell or upgrade. In both cases, we need to have
       
    49     the storage set, else we'll be in trouble...
       
    50 
       
    51   * the path given to the storage is the place where file added through the ui
       
    52     (or in the database before migration) will be located
       
    53 
       
    54   * be ware that by doing this, you can't anymore write queries that will try to
       
    55     restrict on File and Image `data` attribute. Hopefuly we don't do that usually
       
    56     on file's content or more generally on attributes for the Bytes type
       
    57 
       
    58 Now, if you've already added some photos through the web ui, you'll have to
       
    59 migrate existing data so file's content will be stored on the file-system instead
       
    60 of the database. There is a migration command to do so, let's run it in the
       
    61 cubicweb shell (in actual life, you'd have to put it in a migration script as we
       
    62 seen last time):
       
    63 
       
    64 ::
       
    65 
       
    66    $ cubicweb-ctl shell sytweb
       
    67     entering the migration python shell
       
    68     just type migration commands or arbitrary python code and type ENTER to execute it
       
    69     type "exit" or Ctrl-D to quit the shell and resume operation
       
    70     >>> storage_changed('File', 'data')
       
    71     [........................]
       
    72     >>> storage_changed('Image', 'data')
       
    73     [........................]
       
    74 
       
    75 
       
    76 That's it. Now, file added through the web ui will have their content stored on
       
    77 the file-system, and you'll also be able to import files from the file-system as
       
    78 explained in the next part.
       
    79 
       
    80 Step 2: importing some data into the instance
       
    81 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    82 
       
    83 Hey, we start to have some nice features, let give us a try on this new web
       
    84 site. For instance if I have a 'photos/201005WePyrenees' containing pictures for
       
    85 a particular event, I can import it to my web site by typing ::
       
    86 
       
    87   $ cubicweb-ctl fsimport -F sytweb photos/201005WePyrenees/
       
    88   ** importing directory /home/syt/photos/201005WePyrenees
       
    89     importing IMG_8314.JPG
       
    90     importing IMG_8274.JPG
       
    91     importing IMG_8286.JPG
       
    92     importing IMG_8308.JPG
       
    93     importing IMG_8304.JPG
       
    94 
       
    95 .. Note::
       
    96   The -F option tell that folders should be mapped, hence my photos will be
       
    97   all under a Folder entity corresponding to the file-system folder.
       
    98 
       
    99 Let's take a look at the web ui:
       
   100 
       
   101 .. image:: ../../images/tutos-photowebsite_ui1.png
       
   102 
       
   103 Nothing different, I can't see the new folder... But remember our security model!
       
   104 By default, files are only accessible to authenticated users, and I'm looking at
       
   105 the site as anonymous, e.g. not authenticated. If I login, I can now see:
       
   106 
       
   107 .. image:: ../../images/tutos-photowebsite_ui2.png
       
   108 
       
   109 Yeah, it's there! You can also notice that I can see some entities as well as
       
   110 folders and images the anonymous user can't. It just works **everywhere in the
       
   111 ui** since it's handled at the repository level, thanks to our security model.
       
   112 
       
   113 Now if I click on the newly inserted folder, I can see
       
   114 
       
   115 .. image:: ../../images/tutos-photowebsite_ui3.png
       
   116 
       
   117 Great! There is even my pictures in the folder. I can know give to this folder a
       
   118 nicer name (provided I don't intend to import from it anymore, else already
       
   119 imported photos will be reimported), change permissions, title for some pictures,
       
   120 etc... Having a good content is much more difficult than having a good web site
       
   121 ;)
       
   122 
       
   123 
       
   124 Conclusion
       
   125 ~~~~~~~~~~
       
   126 
       
   127 We started to see here an advanced feature of our repository: the ability
       
   128 to store some parts of our data-model into a custom storage, outside the
       
   129 database. There is currently only the :class:`BytesFileSystemStorage` available,
       
   130 but you can expect to see more coming in a near future (our write your own!).
       
   131 
       
   132 Also, we can know start to feed our web-site with some nice pictures!
       
   133 The site isn't perfect (far from it actually) but it's usable, and we can
       
   134 now start using it and improve it on the way. The Incremental Cubic Way :)