<commit_before>.. toctree::

CMS Tutorial
===================

Welcome to the CSM tutorial; throughout this tutorial, we’ll walk you through the creation of a simple Blog application.

This tutorial assumes you have the CSM installed correctly; if not, see the :ref:`installation instructions <installation>`.


About the CMS
-------------

The main objective of the CMS is to replace the bundled django admin interface, that is based on Models, with a modular
and completely customizable new Admin, based on Class Based Views. Also, it provides additional features out of the box,
like a very efficient cache system, a versioning application, scheduling and much more.

Create an admin interface with the CMS is very similar the classic django admin process, but with two important differences:

* instead of creating an admin.py file, you create a cms_bundles.py inside your app folder.
* instead or registering the models using ModelAdmin class, you use Bundles class to embed views or other bundles (as sub_bundle);
  this approach is really powerful because allows you to create very complex hierarchical structures. The Bundles class already contains the
  basic CRUD functionality, that you can extend or replace if you want.

IMPORTANT: At this moment the CMS works only with PostgreSQL database. This first version of the CSM does not support South migrations;
we are planning to implement migrations as soon as they will be integrated into Django's core.


Getting Started
---------------

Let's start our tutorial creating a blog application, just like we do with any normal django app:

::

    python manage.py startapp blog


Then we have to create our models:

::

    from django.db import models
    from django.contrib.auth.models import User

    from scarlet.assets.fields import AssetsFileField
    from scarlet.assets.models import Asset
    from scarlet.versioning import fields
    from scarlet.versioning.models import VersionView, Cloneable
    from scarlet.cms.fields import OrderField

    from taggit.managers import TaggableManager


    class Author(models.Model):
        user = models.OneToOneField(User)
        bio = models.TextField()
        avatar = AssetsFileField(type=Asset.IMAGE, tags=['avatar'])

        def __unicode__(self):
            return u"%s" % (self.user, )

        def fullname(self):
            return self.user.get_full_name()


    class Category(VersionView):
        category = models.CharField(max_length=150)
        slug = models.SlugField(max_length=150, editable=False)

        def __unicode__(self):
            return u"%s" % self.category


    class Post(VersionView):
        date = models.DateField()
        title = models.CharField(max_length=255)
        slug = models.SlugField(max_length=255, editable=False)
        body = models.TextField()
        author = models.ForeignKey(Author)
        category = models.ForeignKey(Category)
        document = AssetsFileField(type=Asset.DOCUMENT, tags=['document'], null=True, blank=True)
        # tags = TaggableManager(blank=True) # disable because it does not work with Publish
        # SEO Section
        keywords = models.TextField(blank=True)
        description = models.TextField(blank=True)

        def __unicode__(self):
            return u"%s" % self.title


    class PostImage(Cloneable):
        post = fields.FKToVersion(Post)
        image = AssetsFileField(type=Asset.IMAGE, tags=['image'])
        caption = models.CharField(max_length=255, blank=True)
        order = OrderField()

        def __unicode__(self):
            if self.caption:
                return self.caption
            else:
                return unicode(self.image)

    Post.register_related(related_name='postimage')

As you can see these are normal django models with a couple of important differences:

* some models subclass :py:class:`VersionView <scarlet.versioning.models.VersionView>` (Category, Post)
  and :py:class:`Cloneable <scarlet.versioning.models.Cloneable>` PostImage instead of models.Model,
  this is how we tell the CMS to make this model versionable. Here you can find more about the :ref:`versioning` system.
* there are some custom fields to manage assets (:py:class:`AssetsFileField <scarlet.assets.fields.AssetsFileField>`),
  ordering (:py:class:`OrderField <scarlet.cms.fields.OrderField>`) and Foreign Key relation
  with other models that have to be cloned when we create a new version of a versioned model object (:py:class:`FKToVersion <scarlet.versioning.fields.FKToVersion>`).
* The last line is necessary to tell the CMS to clone the related Models when you create a new version of a Post model instance.


Creating the Admin
------------------
At this point we have our application and we need to fire up a CMS powered admin: similar to what we do to create the classic admin,
we create a new file inside the app folder called cms_bundles.py, where we put our Classes that inherit from bundles.Bundles instead of admin.ModelAdmin.

The most basic example is the following:
::

    class MyBundle(Bundle):

        class Meta:
            model = MyModel

This way we create a :py:class:`Bundle <scarlet.cms.bundles.Bundle>` that contains the basic CRUD views:<commit_msg>fixed grammar in docs<commit_after>.. toctree::

CMS Tutorial
===================

Welcome to the CSM tutorial; throughout this tutorial, we’ll walk you through the creation of a simple Blog application.

This tutorial assumes you have the CSM installed correctly; if not, see the :ref:`installation instructions <installation>`.


About the CMS
-------------

The main objective of the CMS is to replace the bundled django admin interface, that is based on Models, with a modular
and completely customizable new Admin, based on Class Based Views. Also, it provides additional features out of the box,
like a very efficient cache system, a versioning application, scheduling and much more.

Create an admin interface with the CMS is very similar the classic django admin process, but with two important differences:

* instead of creating an admin.py file, you create a cms_bundles.py inside your app folder.
* instead or registering the models using ModelAdmin class, you use Bundles class to embed views or other bundles (as sub_bundle);
  this approach is really powerful because it allows you to create very complex hierarchical structures. The Bundles class already contains the
  basic CRUD functionality, that you can extend or replace if you want.

IMPORTANT: At this moment the CMS works only with PostgreSQL database. This first version of the CMS does not support South migrations;
we are planning to implement migrations as soon as they will be integrated into Django's core.


Getting Started
---------------

Let's start our tutorial creating a blog application, just like we do with any normal django app:

::

    python manage.py startapp blog


Then we have to create our models:

::

    from django.db import models
    from django.contrib.auth.models import User

    from scarlet.assets.fields import AssetsFileField
    from scarlet.assets.models import Asset
    from scarlet.versioning import fields
    from scarlet.versioning.models import VersionView, Cloneable
    from scarlet.cms.fields import OrderField

    from taggit.managers import TaggableManager


    class Author(models.Model):
        user = models.OneToOneField(User)
        bio = models.TextField()
        avatar = AssetsFileField(type=Asset.IMAGE, tags=['avatar'])

        def __unicode__(self):
            return u"%s" % (self.user, )

        def fullname(self):
            return self.user.get_full_name()


    class Category(VersionView):
        category = models.CharField(max_length=150)
        slug = models.SlugField(max_length=150, editable=False)

        def __unicode__(self):
            return u"%s" % self.category


    class Post(VersionView):
        date = models.DateField()
        title = models.CharField(max_length=255)
        slug = models.SlugField(max_length=255, editable=False)
        body = models.TextField()
        author = models.ForeignKey(Author)
        category = models.ForeignKey(Category)
        document = AssetsFileField(type=Asset.DOCUMENT, tags=['document'], null=True, blank=True)
        # tags = TaggableManager(blank=True) # disable because it does not work with Publish
        # SEO Section
        keywords = models.TextField(blank=True)
        description = models.TextField(blank=True)

        def __unicode__(self):
            return u"%s" % self.title


    class PostImage(Cloneable):
        post = fields.FKToVersion(Post)
        image = AssetsFileField(type=Asset.IMAGE, tags=['image'])
        caption = models.CharField(max_length=255, blank=True)
        order = OrderField()

        def __unicode__(self):
            if self.caption:
                return self.caption
            else:
                return unicode(self.image)

    Post.register_related(related_name='postimage')

As you can see these are normal django models with a couple of important differences:

* Some models subclass :py:class:`VersionView <scarlet.versioning.models.VersionView>` (Category, Post)
  and :py:class:`Cloneable <scarlet.versioning.models.Cloneable>` (PostImage) instead of models.Model,
  this is how we tell the CMS to make this model versionable. Here you can find more about the :ref:`versioning` system.
* There are some custom fields to manage assets (:py:class:`AssetsFileField <scarlet.assets.fields.AssetsFileField>`),
  ordering (:py:class:`OrderField <scarlet.cms.fields.OrderField>`), and Foreign Key relation
  with other models that have to be cloned when we create a new version of a versioned model object (:py:class:`FKToVersion <scarlet.versioning.fields.FKToVersion>`).
* The last line is necessary to tell the CMS to clone the related Models when you create a new version of a Post model instance.


Creating the Admin
------------------
At this point we have our application and we need to fire up a CMS powered admin: similar to what we do to create the classic admin,
we create a new file inside the app folder called cms_bundles.py, where we put our Classes that inherit from bundles.Bundles instead of admin.ModelAdmin.

The most basic example is the following:
::

    class MyBundle(Bundle):

        class Meta:
            model = MyModel

This way we create a :py:class:`Bundle <scarlet.cms.bundles.Bundle>` that contains the basic CRUD views:
{'fraction_non_alphanumeric': 0.0799732467036117, 'fraction_numerical': 0.0028664246130326774, 'mean_word_length': 3.4559386973180075, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7220825', 'n_tokens_mistral': 2804, 'n_tokens_neox': 2649, 'n_words': 1139}