Home

Common Field Types

wq version: 1.1 1.2/1.3
Docs > Overview

Common Field Types

Below are the most common field types used when defining a data model for use with wq. You may also be interested in the full lists of XLSForm question types and Django field types.

If you want to define nested / repeat forms or allow user-defined fields, see Advanced Patterns.

Text Fields

Short Text Input (Char)

XLSForm Definition:

type name label hint required constraint
string [name] Char field Enter some text. wq:length(5)

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.CharField(
        max_length=5,
        null=True,
        blank=True,
        verbose_name="Char field",
        help_text="Enter some text.",
    )

Long Text Input (Text)

XLSForm Definition:

type name label hint required constraint
text [name] Text field Enter some text.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.TextField(
        null=True,
        blank=True,
        verbose_name="Text field",
        help_text="Enter some text.",
    )

Note (XLSForm Only)

XLSForm Definition:

type name label hint required constraint
note [name] This is a note.

Django definition:

Django models do not have a concept corresponding to XLSForm's "note" type. However, it is trivial to edit the HTML form generated by wq to add any formatting or custom text you need.

Numeric Fields

Integer

XLSForm Definition:

type name label hint required constraint
integer [name] Integer field Enter an integer number.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.IntegerField(
        null=True,
        blank=True,
        verbose_name="Integer field",
        help_text="Enter an integer number.",
    )

Decimal / Float

XLSForm Definition:

type name label hint required constraint
decimal [name] Decimal field Enter a decimal number.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.FloatField(
        null=True,
        blank=True,
        verbose_name="Decimal field",
        help_text="Enter a decimal number.",
    )

FIXME: Django also has a separate DecimalField, should probably use that instead?

Choice (Domain) Fields

Static Choices

Static choice fields are useful for quick survey questions with a small set of rarely changing options. "Yes/No" fields can also be implemented this way (though Django also includes a separate BooleanField).

XLSForm Definition:

survey tab

type name label hint required constraint
select_one colors [name] Color Pick a color

choices tab

list name name label
colors red Red
colors green Green
colors blue Blue

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.CharField(
        choices=(
            ("red", "Red"),
            ("green", "Green"),
            ("blue", "Blue"),
        ),
        max_length=5,
        null=True,
        blank=True,
        verbose_name="Pick a color",
    )

Dynamic Choices (ForeignKey)

Dynamic choices make it possible for any user of your application to dynamically update the available domain values without you needing to recompile the application. Under the hood, dynamic choices are implemented as foreign keys to other existing relational tables. In fact, wq does not distinguish in any meaningful way between tables used as domain values versus tables used to manage the actual observation data. This means all tables can be registered with the REST API and managed from the client app (assuming that the appropriate permissions are given to each respective user.) For example, one of the most common schema designs has been to split the observation timeseries into separate "Site" and "Observation" tables, with a ForeignKey pointing from Observation to Site. Users then can manage their list of sites separately from their observational data.

As of wq version 1.0, it is possible to use foreign keys to link parent-child records while working offline, even when the parent record has not yet been synced to the server. The example below assumes that "Site A3" was created on a separate form that has not yet been synced to the server. If that site was selected when this form was saved, wq/outbox.js would ensure that Site A3 is properly synced before attempting to sync this form.

Note: If you need your dynamic choice list to work offline, be sure to set cache="all" when registering the domain model with the router. See the configuration documentation and the example below.

Depending on your use case, it is also possible to define a single form with nested children that populates multiple tables at once - see Advanced Patterns for more information.

XLSForm Definition:

type name label hint required constraint
integer [name] Pick a Site ID wq:ForeignKey("other_app.Site") yes

This is a wq-specific extension to the XLSForm syntax. It assumes that other_app.Site has already been defined in another Django app. If you would like to define multiple tables in the same XLSForm, see Advanced Patterns.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.ForeignKey(
        "other_app.Site",
        verbose_name="Pick a Site ID",
    )

Note: in order to ensure the full site list is available offline, other_app.Site should be configured with cache="all":

# other_app/rest.py
from wq.db import rest
from .models import Site

rest.router.register_model(
    Site,
    fields="__all__",
    cache="all",
)

Date & Time Fields

Date

XLSForm Definition:

type name label hint required constraint
date [name] Date field Enter a date.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.DateField(
        auto_now_add=True,
        verbose_name="Date field",
        help_text="Enter a date.",
    )

Time

XLSForm Definition:

type name label hint required constraint
time [name] Time field Enter a time.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.TimeField(
        auto_now_add=True,
        verbose_name="Time field",
        help_text="Enter a time.",
    )

Date + Time

XLSForm Definition:

type name label hint required constraint
dateTime [name] Date+time field Enter a date and a time.

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.DateTimeField(
        auto_now_add=True,
        verbose_name="Date+time field",
        help_text="Enter a date and a time.",
    )

Files & Photos

Photo

XLSForm Definition:

type name label hint required constraint
image [name] Image field Add an image. yes

Django definition:

from django.db import models

class MyModel(models.Model):
    [name] = models.ImageField(
        upload_to="[folder name]",
        verbose_name="Image field",
        help_text="Add an image.",
    )

This field uses a wq/app.js plugin to display the image preview. For more information, see the documentation for wq/photos.js.

Geospatial Fields

Point

XLSForm Definition:

type name label hint required constraint
geopoint [name] Point field Enter a point. yes

Django definition:

from django.contrib.gis.db import models

class MyModel(models.Model):
    [name] = models.PointField(
        srid=4326,
        verbose_name="Point field",
        help_text="Enter a point.",
    )

This field uses a wq/app.js plugin to display the map editor. For more information, see the documentation for wq/map.js. If you are collecting point locations via GPS, you may also be interested in the wq/locate.js plugin.

LineString

XLSForm Definition:

type name label hint required constraint
geotrace [name] Line string field Enter a line.

Django definition:

from django.contrib.gis.db import models

class MyModel(models.Model):
    [name] = models.LineStringField(
        srid=4326,
        null=True,
        blank=True,
        verbose_name="Line string field",
        help_text="Enter a line.",
    )

This field uses a wq/app.js plugin to display the map editor. For more information, see the documentation for wq/map.js.

Polygon

XLSForm Definition:

type name label hint required constraint
geoshape [name] Polygon field Enter a polygon.

Django definition:

from django.contrib.gis.db import models

class MyModel(models.Model):
    [name] = models.PolygonField(
        srid=4326,
        null=True,
        blank=True,
        verbose_name="Polygon field",
        help_text="Enter a polygon.",
    )

This field uses a wq/app.js plugin to display the map editor. For more information, see the documentation for wq/map.js.