Models and Fields

Models

A Model is the single, canonical source of information about the data your application stores. Models need to be defined and registered. Each attribute of the class represents a MongoDB document field. Each model maps to one MongoDB collection and encapsulates the structure and behavior of that collection in one place.

from djongo import models

class Entry(models.Model):
    _id = models.ObjectIdField()
    headline = models.CharField(max_length=255)    
copy code

Typically, all models are defined inside the models.py file of an app. Naming the definition file as models.py is not mandatory. However, a class is not recognized as model definition unless it is a subclass of djongo.models.Model. A model is registered by registering the app it lives under. For example, if the models for your application live in the module myapp.models (the package structure that is created for an application by the manage.py startapp script), INSTALLED_APPS should read, in part:

INSTALLED_APPS = [
  # ...    
  "myapp.apps.MyappAppConfig",
  # ...
]
copy code

More details regarding models can be found on the Django documentation.

Fields

The most important part of a model – and the only required part of a model – is the list of database fields it defines. Fields are specified by class attributes. Each field in a model should be an instance of an appropriate Field class.

Djongo automatically inherits and supports the following fields:

Field TypeDescription
AutoFieldAn integer field that automatically increments and is used as the default primary key.
BigAutoFieldLike AutoField but stores larger integer values (64-bit).
BigIntegerFieldA 64-bit integer field.
BinaryFieldA field to store raw binary data.
BooleanFieldStores True or False values.
CharFieldA string field for small-to-medium sized text; requires max_length.
DateFieldStores a date (Python datetime.date).
DateTimeFieldStores date and time (Python datetime.datetime).
DecimalFieldA fixed-precision decimal number field.
DurationFieldStores a period of time (Python timedelta).
EmailFieldA CharField that validates input as an email address.
FileFieldA file-upload field; stores the file path.
FilePathFieldStores the file path from the filesystem.
FloatFieldStores floating-point numbers.
ImageFieldA FileField that validates uploaded images.
IntegerFieldA basic integer field.
GenericIPAddressFieldStores IPv4 or IPv6 addresses.
JSONFieldStores JSON-encoded data (dict/list).
PositiveIntegerFieldLike IntegerField but only allows non-negative values.
PositiveSmallIntegerFieldLike PositiveIntegerField but for smaller values.
SmallIntegerFieldLike IntegerField but for smaller values.
SlugFieldA CharField that only allows letters, numbers, hyphens or underscores.
TextFieldA large text field (no max_length required).
TimeFieldStores a time (Python datetime.time).
URLFieldA CharField that validates input as a URL.
UUIDFieldStores a universally unique identifier (uuid).
Relational FieldsFields that define relationships between models
ForeignKeyA many-to-one relationship; requires on_delete.
ManyToManyFieldA many-to-many relationship.
OneToOneFieldA one-to-one relationship; like a unique ForeignKey.

Field options

Each instance of a Field can be instantiated with several options:

OptionDescription
nullStores empty values as NULL in the database if True. Avoid on string fields if possible. Default: False.
blankAllows the field to be blank at the form/validation level if True. Default: False.
choicesAn iterable or mapping restricting the allowed set of values (renders a select widget).
db_columnCustom database column name for the field; defaults to the attribute name.
db_commentDatabase comment for the column, useful for documentation.
db_defaultA database-level default (literal or function). default still takes precedence in Python.
db_indexCreates a database index on the column if True.
db_tablespaceDatabase tablespace name for the field’s index.
defaultDefault value or callable (called for new instances). Cannot be mutable directly.
editableIf False, the field is excluded from admin and any ModelForm. Default: True.
error_messagesOverride default error messages via a dict (keys like null, blank, invalid_choice, etc.).
help_textExtra help text displayed with forms; not HTML-escaped automatically.
primary_keyIf True, designates the field as the model’s primary key. Implies null=False and unique=True.
uniqueEnsures the field value is unique across the table.
unique_for_dateRequires uniqueness with respect to a given date/datetime field’s date portion.
unique_for_monthRequires uniqueness with respect to the month portion of a date/datetime field.
unique_for_yearRequires uniqueness with respect to the year portion of a date/datetime field.
verbose_nameHuman-readable field name (defaults to attribute name with underscores replaced by spaces).
validatorsList of callables used to validate the field’s value.

More details regarding fields can be found on the Django documentation.

MongoDB specific Fields

For working with MongoDB Djongo includes the EmbeddedField and ArrayField

Embedded Field

In MongoDB, you can create and store an embedded document. Djongo lets you do the same by letting you include a child model inside a parent model through the EmbeddedField.

from djongo import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    class Meta:
        abstract = True

class Entry(models.Model):
    _id = models.ObjectIdField()
    blog = models.EmbeddedField(
        model_container=Blog
    )

    headline = models.CharField(max_length=255)
copy code

Nesting Embedded Fields

An EmbeddedField or an ArrayField can be nested inside an EmbeddedField. There is no limitation on the depth of nesting.

from djongo import models

class Tagline(models.Model)
    title = models.CharField(max_length=100)
    subtitle = models.CharField(max_length=100)

    class Meta:
        abstract = True

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.EmbeddedField(model_container=Tagline)

    class Meta:
        abstract = True

class Entry(models.Model):
    _id = models.ObjectIdField()
    blog = models.EmbeddedField(
        model_container=Blog
    )

    headline = models.CharField(max_length=255)    
    objects = models.DjongoManager()
copy code

API Reference

class EmbeddedField(MongoField):
    def __init__(self,
                 model_container: typing.Type[Model],
                 model_form_class: typing.Type[forms.ModelForm] = None,
                 model_form_kwargs: dict = None,
                 *args, **kwargs):
copy code
Arguments
ArgumentTypeDescription
model_containermodels.ModelThe child model class type (not instance) that this embedded field will contain.
model_form_classmodels.forms.ModelFormThe child model form class type of the embedded model.
model_form_kwargsdict()The kwargs (if any) that must be passed to the forms.ModelForm while instantiating it.

Array Field

With MongoDB there can be an array of embedded documents inside the parent document. Djongo allows for the same feature by letting you embed an array of models, inside a parent model.

Example

from djongo import models
from django import forms

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    class Meta:
        abstract = True

class BlogForm(forms.ModelForm):
    class Meta:
        model = Blog
        fields = (
            'name', 'tagline'
        )

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    class Meta:
        abstract = True

class AuthorForm(forms.ModelForm):
    class Meta:
        model = Author
        fields = (
            'name', 'email'
        )

class Entry(models.Model):
    blog = models.EmbeddedField(
        model_container=Blog,
        model_form_class=BlogForm
    )

    headline = models.CharField(max_length=255)    
    authors = models.ArrayField(
        model_container=Author,
        model_form_class=AuthorForm
    )

    objects = models.DjongoManager()
copy code

API Reference

class ArrayField(MongoField):
    def __init__(self,
                 model_container: typing.Type[Model],
                 model_form_class: typing.Type[forms.ModelForm] = None,
                 model_form_kwargs: dict = None,
                 *args, **kwargs):
copy code
Arguments
ArgumentTypeDescription
model_containermodels.ModelThe child model class type (not the instance) that this array field will contain.
model_form_classmodels.forms.ModelFormThe child model form class type of the array model. All child models inside the array must be of the same type. Mixing different types of child models inside the embedded array is not supported.
model_form_kwargsdict()The kwargs (if any) that must be passed to the forms.ModelForm while instantiating it.

The ObjectId Field

For every document inserted into a collection MongoDB internally creates an ObjectID field with the name _id. Reference this field from within the Model:

class Entry(models.Model):
    _id = models.ObjectIdField()
    blog = models.EmbeddedField(
        model_container=Blog,
    )
copy code

By default, the ObjectIdField internally sets primary_key as True. This means the implicitly created id AUTOINCREMENT field will not be created. The Field inherits from the AutoField. An ObjectID will be automatically generated by MongoDB for every document inserted.

Consider using the ObjectIdField in your models if you want to avoid calling Django migrations every time you create a new model.

API Reference

class ObjectIdField(Field):
    def __init__(self, *args, **kwargs):
copy code
Arguments

Same as the Field Base class