File: fields.rst

package info (click to toggle)
django-model-utils 4.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid, trixie
  • size: 552 kB
  • sloc: python: 3,438; makefile: 181
file content (225 lines) | stat: -rw-r--r-- 6,383 bytes parent folder | download
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)