It is important to read the Concepts document before studying the API, otherwise you will not understand what I’m talking about.
In the description of the database models below, it goes without saying that all models have an id field, which is usually not mentioned unless there is something unusual about it.
The Entry model¶
Stores an entry. It is always a subclass that is used, rather than
Entryitself. The constructor of the subclass creates a new entry at the specified path. The parent entry must already exist and the logged on user must have appropriate permissions on the parent entry; otherwise, an exception is raised. If other entries with the same parent entry exist, the entry is added as the last sibling.
Entryobjects have the following database attributes:
A string with the filename of the base template. If empty, it means to use the same template as the parent entry; see
base_templatefor more information.
A foreign key to
Entry(that is, to self). It indicates which entry contains the entry. This attribute can be null; there is one and only one entry that has a null
container, and it is the root entry.
The related_name of this attribute is
all_subentries. Therefore, if you have an entry
myentry.all_subentriesis the entries contained in
myentry. You should not, however, use
all_subentries, unless you have a good reason to do so; instead, use
subentries(), which checks permissions.
A foreign key to
MultilingualGroup, indicating the multilingual group, if any, to which the entry belongs.
The name of the entry.
A foreign key to
django.contrib.auth.models.User, indicating the owner of the entry.
The sequence of the entry in its container: 1 for the first entry, 2 for the second entry, and so on.
A foreign key pointing to the current vobject, that is to the vobject that has the maximum
version_number) for the entry.
This field is redundant, but has to be there to enable some queries to run properly; see these two posts for more information. You should never attempt to set it; Zadig automatically updates it upon saving a new vobject.
Entryhas the following class attributes:
This manager returns all objects. This is a copy of the default django manager. In general, you should avoid using this; you should instead use
objects, which is an
Entryobjects also have the following attributes, properties and methods:
This read-only property returns the absolute URI for the show action of the entry.
action_edit()method is implemented in
Entryand not in its subclasses. When creating a new vobject as a result of edit form submission, it doesn’t know how to process all attributes submitted with the form. It therefore processes only those it can, and then calls this method (which should be implemented in the subclass), which should process any form attributes special to the subclass and modify vobject accordingly.
A list with the alternative language entries. The order in this list is the order with which languages are listed in
A string with the filename the base template the entry should use. This is the base template used to render the page (the base template inherited by the actual template). The result is
btemplate, except if this is empty, in which case the parent’s base template is used; if the top level entry’s
btemplateattribute is also empty, then
Not all kinds of objects can contain all kinds of objects; for example, only blog objects can contain blog post objects; and blog post objects cannot contain other pages. Each
Entrysubclass has the
can_contain()method and the
can_be_contained()class method that indicate what kind of objects can be added as subobjects.
In this text, we use “subobjects” in the containment sense; that is, an object can contain subobjects. We use “subclass” in the usual hierarchical sense.
can_contain()method indicates whether the object is willing to contain a child subobject, where child is an
Entrysubclass; and the
can_be_contained()class method indicates whether the class is willing to create a new subobject of parent, where parent is an
Entrysubclass. You should only call the later, because it calls the former itself, whereas the former does not call the latter and therefore may miss additional restrictions.
Check whether entry is contained, directly or indirectly, in self. Returns
Trueif self is the parent of entry, or the parent of its parent, or any ancenstor, and
django.http.HttpResponseobject with the contents of the entry.
The date the entry was created, i.e. the date of its first vobject. See also
Entryis always subclassed. If you get a grip on an object of type
Entrywhen in fact you need that same object but in its descendant class, and you don’t know which subclass it is, use this property, which gives you the same object but in the proper subclass.
edit_subform(data=None, files=None, new=False)¶
When the object is being edited, a form is shown to the user; this consists of items that are common to all
Entrysubclasses, plus items that are specific to the subclass. The items that are specific to the subclass are the edit subform, and they are a Django form, i.e. a
edit_subform()returns that form. If data (and optionally files) are specified, it returns a bound form (
files=request.FILESis normally specified upon a POST request); otherwise, if new is
True, we are creating a new entry (normally an empty form should be returned); otherwise, we are editing an existing entry (normally an unbound form with the last vobject data as initial data should be returned).
edit_subform()returns an empty form. Subclasses should redefine as needed.
django.http.HttpResponseobject. Depending on the contents of the request object, it either processes a submitted form (either modifying the entry or finding an error in the submitted form) and returns the response, or it returns a page with a form for editing the entry. self must be an
If new is
True, it means that the entry does not exist yet but is in the process of being created. When calling in this manner, self must be an
containermust have been set to the entry of which the new entry will be a child; the other attributes are irrelevant. Depending on the contents of the request object, the method will then either process a submitted form (either creating the entry or finding an error in the submitted form) and return the response, or return a page with a (mostly empty) form for filling in the entry.
Return the entry’s vobject; actually returns a
VObjectdescendant. If version_number is not specified, it returns the latest vobject. An exception is raised if the user does not have permission to view the vobject.
The last modification date of the entry, i.e. the date of its latest vobject.
django.http.HttpResponseobject with the history of the entry.
Move the entry from its current container to target_entry, which will be the new container. Also create a new redirection entry at the old location. Verifies permissions to do all that.
Return the owner full name, if available, otherwise the username.
Return the permissions the logged on user has on the entry.
django.http.HttpResponseobject with the permissions of the entry.
A list of
Stateobjects, which are the possible states to which the workflow allows the current user to move the entry to.
After the user submits the edit form, the subform returned by
edit_subform()must be processed. This method receives the newly created vobject and the submitted subform and processes as needed. The top level method does nothing; it is subclasses that must define how the processing is done.
Rename the entry to the specified new name; it also creates a new redirection entry with the old name.
Move the subentry with
seq=source_seqbefore subentry with
seq=target_seq. source_seq and target_seq are integers. The function changes the order of the children of the entry. The child that has
seq=source_seqis moved before the child that has
seq=target_seq, unless target_seq is one more than the number of children, in which case the child is moved to the end. The other children are renumbered as needed (i.e. their
seqis modified accordingly). Raises an exception if source_seq or target_seq are inappropriate; for example, if source_seq is larger than the number of children, or if source_seq and target_seq are both the same number. Also raises an exception if the user does not have permission to do this.
multilingual_groupso that the entry specified by altpath is an alternative language entry. altpath is a path to another entry.
Note that this method will rarely, if ever return an error: it tries to be smart and do the right thing. Maybe it’s too smart. One case where it raises an exception is if this entry and the other entry are in the same language or they don’t have a language specified.
If the entry specified by altpath does not exist or is inaccessible, the method does nothing.
If one of the entries involved (say A) is already in a multilingual group, and the other entry (say B) is not, it adds B to the multilingual group of A, unless there is already an entry with that language in the group; in that case, it removes A from the group and creates a new multilingual group for A and B.
If both entries are already in multilingual groups, it attempts to join these groups together; but again, if there are language conflicts, it removes one or both of the entries from their old groups as needed.
This read-only property returns the full relative URL path to the entry, starting and ending in a slash. (This is more complicated than just prefixing and suffixing
pathwith a slash, because then the root entry would be two slashes instead of one.) See also
A query set of
Entryobjects, which are the subentries which the user has permission to search, in order.
This class attribute is the name of the template for editing the entry. Frequently the inherited value is OK.
Trueif the current user has either edit or admin permission on the entry. Primarily used by the template to check whether to show the editing buttons.
The class name, such as “PageEntry”, or “ImageEntry”.
This is a class attribute, with a translatable, human readable name for the type, such as “Page” or “Image”.
When called on an entry whose last vobject is a
deletion_mark,it creates an additional vobject identical in content to the vobject before undeletion, thereby reverting to that last vobject.
The default Entry manager¶
Three things are important about the default
Entrymanager (accessible via
- The manager automatically filters objects and does not return
those for which the user does not have search permission (see
request object to understand how this is
done), or objects which are deleted (see
- The manager is inherited by subclasses, contrary to normal django practice.
- The manager has a few additional methods, described below.
Return the entry at the specified path; raise
django.http.Http404if such an entry does not exist or the user does not have permissions to view it (you normally don’t need to handle that exception: it will result in a 404 page).
Generally you should much prefer to use the above method when retrieving Entries, because it will take care of permissions at a low level.
Return a query set that does not contain items that are represented in the default query set in a more appropriate language. For example:
The resulting query set will not contain entries which are in the same multilingual group. If two entries are one the equivalent of the other in another language, only one of them will be included. If one of them is in the effective language, then it will be included, and the other will be excluded; if both are in a language which is not the effective language, then one of them will be included at random.
- The manager automatically filters objects and does not return those for which the user does not have search permission (see request object to understand how this is done), or objects which are deleted (see
The VObject model¶
This model is the parent of models that inherit it using multi-table inheritance, and stores a vobject. This model does not actually store the content of the vobject; this is stored by the descendant model.
VObjectprovides the following attributes and methods:
The date in which the vobject has been created.
If this boolean attribute is
True, then this vobject is a deletion mark, which means that the entry was marked as deleted when this vobject was created. The vobject’s metatags and content are irrelevant in this case.
VObjectis always subclassed. If you get a grip on an object of type
VObjectwhen in fact you need that same object but in its descendant class, and you don’t know which subclass it is, use this property, which gives you the same object but in the proper subclass.
django.http.HttpResponseobject that shows the vobject.
django.http.HttpResponseobject showing the info for the vobject.
Used internally. When a vobject is deleted (i.e. has
deletion_markset), then this method is called instead of its other actions This method decides if it should return a response or whether it should raise a
Create and save an exact copy of the vobject; the only thing that is different in the newly created vobject is its id and date. Used for reverting an entry to an old vobject.
VObjecthas a custom manager:
objectsis similar to the default manager, except that it has an additional method:
Return the vobject that corresponds to the entry at the specified path. If version_number is not specified, it returns the latest vobject.
django.http.Http404is raised if the entry does not exist or the user does not have permissions to view it (you normally don’t need to handle that exception: it will result in a 404 page).
Other core models¶
Permissions assigned to the entry besides those assigned to its state. Has three attributes:
permission, all foreign keys to the respective model.
Contains languages. It has only one field,
id, storing the language id, as a 5-character long string, in the form “en” or “en_us” etc.
A lookup that lists permissions: “view”, “edit”, “admin”, “search”, “delete”. Has only a
A Lentity represents either a user or a group, and is used whenever any of the two can be used; for example, a certain permission can be given either to a user or to a group. It has three attributes:
special. The former two are foreign keys to
special, must be not null; the other two must be null. If
useris not null, the
Lentityrepresents a user. If
groupis not null, the
Lentityrepresents a group.
special, besides null, can have one of the following values:
These values denote any user (including the anonymous user), and any logged on user.
This value denotes the owner of the entry. This is useful in cases where we need to generalize the owner; for example, in state-transition rules, such as “the owner of an object has permission to publish it”.
These values indicate the set of users who have the respective permission. This can also used in state-transitions, for example: “users who have edit permission may publish”. Care should be taken to avoid circles, such as “a user with edit permission may edit”, so
StatePermissionshould generally not refer to such special users.
There is the following method:
Trueif the lentity represents user or a group that contains user. user is a
django.contrib.auth.models.Userinstance. entry should also be supplied, in case the lentity is
PERM_SEARCH; in these cases, whether user is a member of the lentity depends on the entry.
A list of states. Contains only a
A state is a collection of permissions. This model stores the permissions that comprise the state. It has three attributes,
permission, which are foreign keys to
Permission, and designate that said lentity has said permission on said state.
A state transition. Has three attributes,
target_state(both foreign keys to
lentity(foreign key to
Lentity, the user or, more commonly, group who has permission to perform this transition).
A workflow is a collection of states and state-transition rules. The model has three attributes:
name, which is a string,
state_transitions. The last two are many to many fields to
Stores the metatags of a vobject. Has five attributes:
languageare foreign keys to the respective models;
descriptionare strings. Also has method
get_short_title(), which returns the short title, or the title if the short title is empty. The related name is metatags.
The default manager has an additional property,
default, which returns an appropriate set of metatags. Normally the manager has access to the request object, in which case it returns the metatags in the effective language. Failing that (because the request object is unavailable, or because there are no metatags in the effective language), it returns the metatags in the language of the vobject; and if such a set does not exist, it returns a random set of metatags.
A lookup storing content formats, such as “text/html” or “text/x-rst”. Has only a
Stores the multilingual groups. It has no field besides id, as it is only used to group multilingual entries together through their
multilingual_groupfield. It has a
check()method, which checks for integrity: it deletes the group if it contains less than two entries, checks that there are no multiple language occurrences in the group, makes other similar checks, and raises
ValidationErrorif a check fails.
VObjectand designates a file. Has attribute
content, a file field.
The functions below are in module zadig.core.utils.
Return a list with the path items. Roughly
path.split('/')but not confused by trailing slash, will ignore a starting slash, will work on an empty string or single slash, and it always includes an empty string as the first path item, which stands for the root entry.
Return a string with the path items joined into a path. path_items is a sequence of strings (supplied either as string arguments, or as a single sequence argument); each string may contain slashes. Roughly
'/'.join(path_items)but will not result in duplicate slashes (strips leading and trailing slashes from each path item before joining), and the result never includes a trailing or leading slash.
Return the path to the current entry. This is something like
request.path, but does not include any directive like
__edit__and so on.
Return a queryset of
Lentityobjects that either are or contain user, which is a
For information about these functions, see the request object.
Sanitize the HTML provided and return a sanitized version. This is done for two reasons: (a) to avoid cross site scripting attacks; (b) to discourage users from using too much markup. It only allows specific (whitelisted) tags and specific (whitelisted) attributes, deleting all the rest, and it also sanitizes the content of href and src attributes, by allowing only specific (whitelisted) URL schemes. The whitelists are hardwired in this version.