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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
Fields
======
.. _StatusField:
StatusField
-----------
A simple convenience for giving a model a set of "states."
``StatusField`` is a ``CharField`` subclass that expects to find a
class attribute called ``STATUS`` on its model or you can pass
``choices_name`` to use a different attribute name, and uses that as
its ``choices``. Also sets a default ``max_length`` of 100, and sets
its default value to the first item in the ``STATUS`` choices:
.. code-block:: python
from model_utils.fields import StatusField
from model_utils import Choices
class Article(models.Model):
STATUS = Choices('draft', 'published')
# ...
status = StatusField()
(The ``STATUS`` class attribute does not have to be a :ref:`Choices`
instance, it can be an ordinary list of two-tuples).
Using a different name for the model's choices class attribute
.. code-block:: python
from model_utils.fields import StatusField
from model_utils import Choices
class Article(models.Model):
ANOTHER_CHOICES = Choices('draft', 'published')
# ...
another_field = StatusField(choices_name='ANOTHER_CHOICES')
``StatusField`` does not set ``db_index=True`` automatically; if you
expect to frequently filter on your status field (and it will have
enough selectivity to make an index worthwhile) you may want to add this
yourself.
.. _MonitorField:
MonitorField
------------
A ``DateTimeField`` subclass that monitors another field on the model,
and updates itself to the current date-time whenever the monitored
field changes:
.. code-block:: python
from model_utils.fields import MonitorField, StatusField
class Article(models.Model):
STATUS = Choices('draft', 'published')
status = StatusField()
status_changed = MonitorField(monitor='status')
(A ``MonitorField`` can monitor any type of field for changes, not only a
``StatusField``.)
If a list is passed to the ``when`` parameter, the field will only
update when it matches one of the specified values:
.. code-block:: python
from model_utils.fields import MonitorField, StatusField
class Article(models.Model):
STATUS = Choices('draft', 'published')
status = StatusField()
published_at = MonitorField(monitor='status', when=['published'])
SplitField
----------
A ``TextField`` subclass that automatically pulls an excerpt out of
its content (based on a "split here" marker or a default number of
initial paragraphs) and stores both its content and excerpt values in
the database.
A ``SplitField`` is easy to add to any model definition:
.. code-block:: python
from django.db import models
from model_utils.fields import SplitField
class Article(models.Model):
title = models.CharField(max_length=100)
body = SplitField()
``SplitField`` automatically creates an extra non-editable field
``_body_excerpt`` to store the excerpt. This field doesn't need to be
accessed directly; see below.
Accessing a SplitField on a model
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When accessing an attribute of a model that was declared as a
``SplitField``, a ``SplitText`` object is returned. The ``SplitText``
object has three attributes:
``content``:
The full field contents.
``excerpt``:
The excerpt of ``content`` (read-only).
``has_more``:
True if the excerpt and content are different, False otherwise.
This object also has a ``__unicode__`` method that returns the full
content, allowing ``SplitField`` attributes to appear in templates
without having to access ``content`` directly.
Assuming the ``Article`` model above:
.. code-block:: pycon
>>> a = Article.objects.all()[0]
>>> a.body.content
u'some text\n\n<!-- split -->\n\nmore text'
>>> a.body.excerpt
u'some text\n'
>>> unicode(a.body)
u'some text\n\n<!-- split -->\n\nmore text'
Assignment to ``a.body`` is equivalent to assignment to
``a.body.content``.
.. note::
a.body.excerpt is only updated when a.save() is called
Customized excerpting
~~~~~~~~~~~~~~~~~~~~~
By default, ``SplitField`` looks for the marker ``<!-- split -->``
alone on a line and takes everything before that marker as the
excerpt. This marker can be customized by setting the ``SPLIT_MARKER``
setting.
If no marker is found in the content, the first two paragraphs (where
paragraphs are blocks of text separated by a blank line) are taken to
be the excerpt. This number can be customized by setting the
``SPLIT_DEFAULT_PARAGRAPHS`` setting.
UUIDField
----------
A ``UUIDField`` subclass that provides an UUID field. You can
add this field to any model definition.
With the param ``primary_key`` you can set if this field is the
primary key for the model, default is True.
Param ``version`` is an integer that set default UUID version.
Versions 1,3,4 and 5 are supported, default is 4.
If ``editable`` is set to false the field will not be displayed in the admin
or any other ModelForm, default is False.
.. code-block:: python
from django.db import models
from model_utils.fields import UUIDField
class MyAppModel(models.Model):
uuid = UUIDField(primary_key=True, version=4, editable=False)
UrlsafeTokenField
-----------------
A ``CharField`` subclass that provides random token generating using
python's ``secrets.token_urlsafe`` as default value.
If ``editable`` is set to false the field will not be displayed in the admin
or any other ModelForm, default is False.
``max_length`` specifies the maximum length of the token. The default value is 128.
.. code-block:: python
from django.db import models
from model_utils.fields import UrlsafeTokenField
class MyAppModel(models.Model):
uuid = UrlsafeTokenField(editable=False, max_length=128)
You can provide your custom token generator using the ``factory`` argument.
``factory`` should be callable. It will raise ``TypeError`` if it is not callable.
``factory`` is called with ``max_length`` argument to generate the token, and should
return a string of specified maximum length.
.. code-block:: python
import uuid
from django.db import models
from model_utils.fields import UrlsafeTokenField
def _token_factory(max_length):
return uuid.uuid4().hex
class MyAppModel(models.Model):
uuid = UrlsafeTokenField(max_length=32, factory=_token_factory)
|