Preamble
I’m quite new to QGIS and QField and taking the steep learning curve as I may need some in-depth knowledge of them soon.
To make it easier to talk with you and may allow others an easy entry to field surveys, I want to share my learning with a simple project and ask the communnity to either confirm or comment my statements.
Imagine you represent an architect’s office which develops an area with housing and commercial buildings. You control and record the site progress using QField. Besides people within your company it shall be used by construction workers as well to document progress; moreover, the client would like to use it to see the progress.
Until it is confirmed that my statements are correct, I exclude the last two mentioned roles (construction workers and client).
I keep it at a higher level to emphasise how to deal with similarities (e.g. types of building).
- similarity (e.g. housing and commercial buildings).
- individual properties
- frequently repeating properties or structures.
(I know that there are specialized platforms around to provide solutions for exactly this, but I could not think of a more common example which everyone understands naturally).
Background is Inspection of 200 Underground Chambers – Feasibility Question - Ask the Community - QField community
Structure
The principles I derived
After reading endless documentation (
) , watching videos and interacting with the AI, I have identified some basic rules that you need to keep in mind:
-
unique and recurring properties
-
Everything that can occur multiple times → its own layer. If you find yourself writing “Room 1, Room 2, Room n” as fields in a single layer, stop — you need a child layer with a relation. Each repeating object becomes a row in that child layer’s attribute table, linked to the parent via a foreign key. In QGIS, this relation is defined under Project → Properties → Relations, and surfaced in the parent form as a Relation Editor widget (“+ Add Room” button). Repeating objects are NEVER modeled as fields on the master layer.
Relation Editor:
-
Everything that occurs exactly once per object → attribute. Address, building category, number of floors — these stay as fields on the master layer.
Example — Building with 5 rooms:
Layer “Building” — attribute table:
building_id address number_of_floors G-001 Bahnhofstr. 5 2 Layer “Room” — attribute table (child layer, one row per room):
room_id building_id (FK) size floor Z-001 G-001 18 m² GF Z-002 G-001 14 m² GF Z-003 G-001 22 m² 1F Z-004 G-001 12 m² 1F Z-005 G-001 9 m² 1F The
building_idforeign key connects each room to its building. The field worker taps “+ Add Room” in the Relation Editor to create each row individually — explicit, controlled, robust. -
-
Everything that belongs spatially, functionally, or logically to the master object → attach it as a child layer underneath, don’t pull it into the master layer’s fields and don’t promote it to its own master layer. Example: outdoor areas (balcony, garden, terrace) belong to the building — they are a child layer under “Building” with a foreign key, not a separate top-level master layer “Outdoor Areas”.
-
Conditional logic belongs in the form, not in the structure. Example: the “floor” attribute of a room is only relevant in multi-story buildings. This is solved with a visibility expression like
attribute(@current_parent_feature, 'number_of_floors') > 1— not by creating separate layers for single-story and multi-story rooms. -
A form describes an object, not a structure. The form doesn’t define what exists — the data model does.
-
Status is a data state, not a form state. Approval workflows are driven by status fields and database permissions, not by different form variants.
-
QField executes what QGIS has cleanly modeled — nothing more, nothing less.
The building analogy — how I got there
I started with two competing structures and found that neither was right until I applied the principles above.
Wrong approach (what I did first):
Modeling “Room 1”, “Room 2”, “Room n” as separate attribute groups inside the building layer, with conditional visibility per room. This doesn’t scale and violates principle 1.
Correct approach:
+ Building (master layer)
- building_id
- address
- building_category (residential / commercial)
- building_type (if residential: single-family / multi-family)
- building_type (if commercial: lab / office)
- number_of_floors
++ Apartment (child layer, only for multi-family)
- apartment_id
- building_id (FK)
- apartment_type
- floor
+++ Room (child layer, for BOTH single-family and multi-family)
- room_id
- parent_type (building | apartment)
- parent_id (FK)
- size
- floor (visibility: only if single-family AND floors > 1)
++ Commercial_Equipment (child layer)
- building_id (FK)
- special_equipment (checkboxes)
- open_plan_area
- number_of_fixed_rooms
++ Outdoor_Area (child layer)
- outdoor_id
- building_id (FK)
- type (balcony | garden | terrace | courtyard | roof terrace)
- area
- location (optional)
- usage
++ Utility_Connection (child layer)
- connection_id
- building_id (FK)
- medium (electricity | thermal | fresh water | waste water)
- status
Master form layout in QGIS sketcher
based on the above said you have the following form in the master layer (buildings)
+ Building
- address
- building_type
─────────────────────
Apartments [+ Add Apartment] ← Relation Editor
─────────────────────
Rooms [+ Add Room] ← Relation Editor
─────────────────────
Outdoor Areas [+ Add Balcony] ← Relation Editor
[+ Add Garden]
[+ Add Terrace]
─────────────────────
Utility Connections [+ Add Connection] ← Relation Editor
Field workflow:
- User creates the building
- → optionally enters
number_of_rooms = 5 - → navigates to the Rooms section
- → taps “+ Add Room” five times
- → fills each room individually.
Explicit, controlled, robust.