Skip to main content

Overview

Projects are the core organizational unit in QFieldCloud. Each project represents a QGIS project that can be synchronized between QGIS desktop and QField mobile app. Projects contain geographic data, configurations, and metadata required for field data collection.

Project Model

The Project model in QFieldCloud is defined in core/models.py:1066 and represents a directory structure containing QGIS project files and associated data.

Key Fields

  • id: UUID primary key, auto-generated
  • name: Project name (alphanumeric, underscores, hyphens, dots allowed)
  • description: Optional text description
  • owner: Foreign key to User (Person or Organization)
  • is_public: Boolean flag for project visibility
  • the_qgis_file_name: Name of the main QGIS project file (.qgs/.qgz)
  • project_details: JSON field containing parsed project metadata
  • created_at: Timestamp of project creation
  • updated_at: Timestamp of last update
  • file_storage: Storage backend name (e.g., “s3”, “minio”)
  • file_storage_bytes: Cached size of project files

Creating a Project

API Endpoint

POST /api/v1/projects/

Request Body

{
  "name": "field_survey_2024",
  "description": "Field data collection for Q1 2024",
  "owner": "username",
  "is_public": false
}

Example with cURL

curl -X POST https://app.qfield.cloud/api/v1/projects/ \
  -H "Authorization: Token YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my_project",
    "owner": "username",
    "is_public": false
  }'

Permissions

To create a project, the authenticated user must:
  • Have an active account
  • Have sufficient storage quota
  • Be the owner or have admin rights to the organization (if creating for an organization)
See core/views/projects_views.py:49 for permission checks.

Project Visibility

Public Projects

Projects with is_public=True:
  • Visible to all authenticated users
  • Read-only access for non-collaborators
  • Owner and collaborators retain edit permissions
  • Listed in the public projects endpoint
GET /api/v1/public-projects/

Private Projects

Projects with is_public=False:
  • Only visible to owner and collaborators
  • Access controlled by collaboration roles
  • Subject to subscription limits on collaborators

Project Settings

File Storage Configuration

Projects can be configured to use different storage backends:
file_storage = models.CharField(
    max_length=100,
    default=get_project_file_storage_default,
    validators=[validators.file_storage_name_validator],
)
Supported storage backends are configured in Django’s STORAGES setting.

Attachment Storage

Separate storage configuration for attachment files:
attachments_file_storage = models.CharField(
    max_length=100,
    default=get_project_attachments_file_storage_default,
)
Attachment files are identified by special directories (default: “DCIM”).

Version Control

Control file version retention:
storage_keep_versions = models.PositiveIntegerField(
    null=True,
    blank=True,
    validators=[MinValueValidator(1), MaxValueValidator(100)],
)
When set, limits the number of file versions kept. Falls back to the owner’s subscription plan default.

Conflict Resolution

overwrite_conflicts = models.BooleanField(
    default=True,
    help_text="Automatically overwrite conflicts or require manual resolution"
)

Restricted Project Files

has_restricted_projectfiles = models.BooleanField(
    default=False,
    help_text="Restrict QGIS project file modifications to managers and administrators"
)

Project Lifecycle

1. Creation

When a project is created:
  • UUID is auto-generated
  • Owner’s storage quota is checked
  • Storage backend is initialized
  • Timestamps are set

2. File Upload

After creation, upload QGIS project files:
POST /api/v1/files/{projectid}/{filename}/
When a .qgs or .qgz file is uploaded:
  • A ProcessProjectfileJob is automatically triggered
  • Project metadata is extracted into project_details
  • Layer information is parsed and validated

3. Active Use

During active use:
  • Files can be uploaded/downloaded
  • Deltas are created from mobile edits
  • Packaging jobs prepare data for offline use
  • Collaborators can be added/removed

4. Deletion

DELETE /api/v1/projects/{projectid}/
Deleting a project:
  • Removes all associated files from storage
  • Deletes all collaborators
  • Removes all jobs and deltas
  • Cannot be undone
See core/views/projects_views.py:168 for deletion logic.

Project Status

Projects have computed status based on current state:

Status Values

  • ok: Project is ready to use
  • busy: Background jobs are running
  • failed: Project has configuration errors

Status Codes

  • ok: No issues
  • failed_process_projectfile: Missing or invalid QGIS project file
  • too_many_collaborators: Exceeds subscription limit
See core/models.py:1801 for status computation logic.

Querying Projects

List User’s Projects

GET /api/v1/projects/
Returns projects where the user is:
  • The owner
  • A collaborator
  • Organization member (for organization-owned projects)

Filtering

The ProjectQueryset.for_user() method filters projects:
projects = Project.objects.for_user(user, skip_invalid=False)
Projects are annotated with:
  • user_role: The user’s role on the project
  • user_role_origin: How the role was assigned (owner, collaborator, organization, etc.)
  • user_role_is_valid: Whether the role is currently valid
See core/models.py:976 for query implementation.

Special Project Types

Shared Datasets Project

A special project named shared_datasets used for localized datasets:
SHARED_DATASETS_PROJECT_NAME = "shared_datasets"
This project:
  • Stores shared data layers
  • Cannot contain QGIS project files
  • Provides data to other projects via localized layers

API Reference

Retrieve Project

GET /api/v1/projects/{projectid}/

Update Project

PATCH /api/v1/projects/{projectid}/
{
  "description": "Updated description",
  "is_public": true
}

Transfer Ownership

Change project owner (requires sufficient quota):
PATCH /api/v1/projects/{projectid}/
{
  "owner": "new_owner_username"
}
See core/views/projects_views.py:144 for transfer validation.

Build docs developers (and LLMs) love