summaryrefslogtreecommitdiff
path: root/docs/extending_entry_model.rst
blob: faa00e5e2a9278eac6e125da83e7a90ecfb48132 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
=====================
Extending Entry model
=====================

.. module:: zinnia.models

The :class:`Entry` model bundled in Zinnia can now be extended and customized.

This feature is useful for who wants to add some fields in the model,
or change its behavior. It allows Zinnia to be a really generic
and reusable application.

Imagine that I find Zinnia really great, but that is misses some fields
or features to be the blog app that I need for my Django project.
For example I need to add a custom field linking to an image gallery,
2 solutions:

* I search for another Django blogging app fitting my needs.
* I make a monkey patch, but I won't be able to upgrade to future releases.

These 2 solutions are really bad, that's why Zinnia provides
a third solution.

* Customizing the model noninvasively with the power of inheritance.

How do we do that?

In fact, simply by creating an abstract model inherited from
:class:`EntryBaseModel`, adding fields or/and overriding his methods, and
registering it with the :setting:`ZINNIA_ENTRY_BASE_MODEL` setting in your
project.

Example for adding a gallery field. ::

  from django.db import models
  from mygalleryapp.models import Gallery
  from zinnia.models import EntryAbstractClass

  class EntryGallery(EntryAbstractClass):
    gallery = models.ForeignKey(Gallery)

    class Meta:
      abstract = True


Now you register the :class:`EntryGallery` model like this in your
project's settings. ::

  ZINNIA_ENTRY_BASE_MODEL = 'appname.custom_entry.EntryGallery'


Finally extend the entry's admin class to show your custom field. ::

  from django.contrib import admin
  from zinnia.models import Entry
  from zinnia.admin.entry import EntryAdmin
  from django.utils.translation import ugettext_lazy as _

  class EntryGalleryAdmin(EntryAdmin):

    # In our case we put the gallery field
    # into the 'Content' fieldset
    fieldsets = ((_('Content'), {'fields': (
      'title', 'content', 'image', 'status', 'gallery')})) + \
      EntryAdmin.fieldsets[1:]

  admin.site.unregister(Entry)
  admin.site.register(Entry, EntryGalleryAdmin)


You can see another example in the files :file:`zinnia/plugins/placeholder.py`
and :file:`zinnia/plugins/admin.py`.

.. note:: You have to respect **4 important rules** :

          #. Do not import the Entry model in your file defining the
             extended model because it will cause a circular importation.

          #. Do not put your abstract model in a file named models.py,
             it will not work for a non obvious reason.

          #. Don't forget to tell that your model is abstract. Otherwise a
             table will be created and the extending process will not work
             as expected.

          #. If you extend the Entry model after the syncdb command, you
             will have to reset the Zinnia application to reflect your
             changes.