不動産リストバックエンドテンプレート
Flutter — スキーマ、地理クエリ & AI ガイド
Back4app 上のプロダクション準備が整った Flutter 不動産リストバックエンド:リスト、リード、お気に入り、地理クエリ、ER 図、データ辞書、JSON スキーマ、API プレイグラウンド、数分でデプロイするためのワンクリック AI エージェントプロンプト。
主なポイント
このページでは、プロダクション対応の不動産スキーマ、ワンクリックAIプロンプト、段階的なFlutterコードを提供します。これにより、バックエンドを構築することなく物件リストアプリを出荷できます。
- 数分でデプロイ — AIエージェントプロンプトを貼り付けて、物件リスト、地理検索、リードキャプチャ、お気に入り機能を備えたアプリを実行できます。
- すぐに使える地理クエリ — Property.location (GeoPoint) は「私の近くの物件」と地図ベースの検索のために $nearSphere をサポートしています。
- Flutter-ネイティブSDK — 型付きオブジェクト、async/await、オプションのオフラインピン留め、そして新しいリスティングのためのLive Queries。
- REST + GraphQL — 両方のAPIは自動生成され、ステータス、ベッド数、価格でフィルタリングできます。距離または日付でソートします。
- 4つのクラス — _User (組み込み)、Property、Lead (問い合わせ)、Favorite (保存されたリスティング)。
Flutter不動産リスティングバックエンドテンプレートとは?
Back4appは不動産リスティングアプリに最適なバックエンドサービス(BaaS)で、管理されたバックエンド、認証、地理クエリ、13以上の技術用SDKを提供します。Flutter不動産リスティングバックエンドテンプレートは、Back4app上の事前構築されたスキーマで、認証(User)、リスティング(Property)、問い合わせ(Lead)、保存された物件(Favorite)を含みます。地理クエリ、リードキャプチャ、ワンクリックAIエージェントプロンプトを取得できます。Flutterフロントエンドを接続し、数分で動作する物件リストアプリを出荷します。
最適な用途:
概要
不動産リスティングアプリには、プロパティのCRUD、地図検索用の地理クエリ、リードキャプチャ(プロパティごとの問い合わせ)、ユーザーのお気に入りが必要です。内部では、認証、位置情報付きのプロパティ(GeoPoint)、プロパティにリンクされたリード、お気に入りとしてユーザーとプロパティをリンクする必要があります。
スキーマ(下のER図を参照)には、ユーザー、プロパティ、リード、お気に入りが含まれています。Back4app Flutter SDKを使用すると、プロパティ(地理を含む)をクエリし、リードを作成し、お気に入りを管理できます — カスタムAPIレイヤーを作成することなく。
コア不動産リスティング機能
このバックエンドテンプレートには、以下の機能が標準で含まれています。
物件リスティング
タイトル、価格、住所、位置 (GeoPoint)、ベッド数、バスルーム数、ステータスを持つ物件。ステータス、価格、または地理でリストおよびフィルタリングします。
リードキャプチャ
物件へのリードリンクの名前、メール、電話、メッセージを取得します。リスティング詳細ページからのお問い合わせをキャプチャします。
保存した物件
お気に入りリンクはユーザーと物件を関連付けます。現在のユーザーのお気に入りをリストし、リスティング詳細から追加または削除します。
地理クエリ
Property.location (GeoPoint) は $nearSphere をサポートしています。ポイントの近くの物件を見つけ、距離でソートします。
ユーザーと権限
組み込みの _User; 物件の作成/更新をエージェントに制限します; リストと詳細の公開読み取り。
Back4appで不動産リスティングバックエンドを構築する理由は?
Back4appは、地理クエリとリードキャプチャを備えた準備済みのバックエンドを提供するため、RESTグルーを記述したり、認証を自分で管理したりすることなく、プロパティリスティングアプリを構築できます。
- •ジオクエリとSDK: Property.location (GeoPoint) は $nearSphere をサポートしています; SDK は Property と Lead を型安全に保ちます。
- •リードキャプチャとお気に入り: Lead クラスは物件ごとの問い合わせを保存します; お気に入りはユーザーと物件をリンクして保存されたリスティングを提供します。
- •Live Queries: Property または Favorite の変更を購読して、UI をリアルタイムで更新します。
すべてのスタックに対して同じスキーマとAPI — 後でクライアントを切り替えてもバックエンドを変更する必要はありません。
コアの利点
迅速に出荷し、アプリに集中できる本番環境向けの不動産バックエンド。
迅速に出荷、バックエンドコード不要
REST & GraphQL API と準備されたスキーマ — アプリを接続して開始。
すぐに使えるジオクエリ
$nearSphere を使用してポイント近くの物件を見つけ、距離でソート。
リードキャプチャ
リードクラスは名前、メール、電話、メッセージ、および物件ポインタを保存。
組み込みの認証
ユーザーのサインアップ、ログイン、およびセッション管理; お気に入りとリスト管理を制限。
オフラインで動作
ローカルピン留めにより、物件とお気に入りがオフラインで利用可能になり、再接続時に同期。
数分でデプロイ
AIエージェントを使用して、このテンプレートから不動産アプリを作成およびデプロイ。
試してみる準備はできましたか?
Back4app AIエージェントに不動産リスティングのバックエンドを作成させ、Flutter フロントエンドを接続し、デプロイします — すべて単一のプロンプトから。
無料で開始 — 月50件のAIエージェントプロンプト、クレジットカード不要
技術スタック
この不動産リスティングテンプレートを支えるすべてを一目で。
ER図
Flutter不動産リスティングデータモデルのためのエンティティ-リレーションシップ図。
スキーマ: _User, Property, Lead, FavoriteはlistedBy, property, userのポインタを持つ。
図のソースを表示
erDiagram
_User {
String objectId PK
String username
String email
String password
Date createdAt
Date updatedAt
}
Property {
String objectId PK
String title
String description
Number price
String address
GeoPoint location
Number beds
Number baths
Number area
String propertyType
String status
Pointer listedBy FK
Date createdAt
Date updatedAt
}
Lead {
String objectId PK
String name
String email
String phone
String message
Pointer property FK
Date createdAt
Date updatedAt
}
Favorite {
String objectId PK
Pointer user FK
Pointer property FK
Date createdAt
Date updatedAt
}
_User ||--o{ Property : "listedBy"
_User ||--o{ Favorite : "user"
Property ||--o{ Lead : "property"
Property ||--o{ Favorite : "property"
統合フロー
Auth-to-CRUDシーケンス: あなたのFlutterアプリがBack4appと通信する方法 — ログイン、プロパティをクエリ(ジオ付き)、リードを作成、お気に入りを管理。
図のソースを表示
sequenceDiagram
participant User
participant App as Flutter App
participant Back4app as Back4app Cloud
User->>App: Login
App->>Back4app: Authenticate (username, password)
Back4app-->>App: Session token
App-->>User: Logged in
User->>App: Load data
App->>Back4app: Query Property and Lead
Back4app-->>App: List of Property / Lead
App-->>User: Show list
User->>App: Create or update
App->>Back4app: Save Property
Back4app-->>App: Property (objectId)
App-->>User: Updated listデータ辞書
スキーマ内のすべてのクラスの完全なフィールドリファレンス。
| フィールド | タイプ | 説明 | 必須 |
|---|---|---|---|
| objectId | String | Auto-generated unique identifier | 自動 |
| title | String | Listing title | |
| description | String | Full listing description | — |
| price | Number | Asking or rental price | — |
| address | String | Street address | — |
| location | GeoPoint | Lat/lng for geo-queries and map display | — |
| beds | Number | Number of bedrooms | — |
| baths | Number | Number of bathrooms | — |
| area | Number | Area in sq ft or sq m | — |
| propertyType | String | e.g. house, apartment, land | — |
| status | String | e.g. for_sale, for_rent, sold | — |
| listedBy | Pointer<_User> | User who created the listing | — |
| createdAt | Date | Auto-generated creation timestamp | 自動 |
| updatedAt | Date | Auto-generated last-update timestamp | 自動 |
14 フィールドが Property にあります
セキュリティと権限
ACL とクラスレベルの権限がこの不動産スキーマ内のデータをどのように保護するか。
プロパティと公開読み取り
プロパティリストと詳細の公開読み取りを許可し、作成/更新/削除を認証されたユーザー(例:リスティングエージェント)に制限します。
クラスレベルの権限
CLP はクラスごとに作成/読み取り/更新/削除を制限します。リードの作成は公開可能ですが、Favorite と Property の書き込みは通常認証を必要とします。
ポインタベースの関係
_UserにリンクするlistedByプロパティ; Favoriteはユーザーとプロパティをリンクします。必要に応じてCloud Codeを使用して所有権を強制します。
スキーマ (JSON)
生のJSONスキーマ定義 — Back4appアプリにコピーして使用するか、API経由でインポートします。
{
"classes": [
{
"className": "Property",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"title": {
"type": "String",
"required": true
},
"description": {
"type": "String",
"required": false
},
"price": {
"type": "Number",
"required": false
},
"address": {
"type": "String",
"required": false
},
"location": {
"type": "GeoPoint",
"required": false
},
"beds": {
"type": "Number",
"required": false
},
"baths": {
"type": "Number",
"required": false
},
"area": {
"type": "Number",
"required": false
},
"propertyType": {
"type": "String",
"required": false
},
"status": {
"type": "String",
"required": false
},
"listedBy": {
"type": "Pointer",
"targetClass": "_User",
"required": false
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
},
{
"className": "Lead",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"name": {
"type": "String",
"required": true
},
"email": {
"type": "String",
"required": true
},
"phone": {
"type": "String",
"required": false
},
"message": {
"type": "String",
"required": false
},
"property": {
"type": "Pointer",
"targetClass": "Property",
"required": false
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
},
{
"className": "Favorite",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"user": {
"type": "Pointer",
"targetClass": "_User",
"required": false
},
"property": {
"type": "Pointer",
"targetClass": "Property",
"required": false
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
},
{
"className": "_User",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"username": {
"type": "String",
"required": true
},
"email": {
"type": "String",
"required": true
},
"password": {
"type": "String",
"required": true
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
}
]
}AIエージェントで構築
このテンプレートから実際の不動産リスティングアプリを構築するためにBack4app AIエージェントを使用します: フロントエンド、バックエンド(このスキーマ、認証、地理クエリ、およびAPI)を作成し、デプロイします — 手動設定は不要です。
Back4appでこの正確なスキーマと動作で不動産リストアプリを作成してください。 スキーマ: 1. _User(Back4app組み込み): username(String、必須)、email(String、必須)、password(String、必須);objectId、createdAt、updatedAt(システム)。 2. Property: title(String、必須)、description(String)、price(Number)、address(String)、location(GeoPoint)、beds(Number)、baths(Number)、area(Number)、propertyType(String)、status(String;例 for_sale、for_rent、sold)、listedBy(_UserへのPointer);objectId、createdAt、updatedAt(システム)。 3. Lead: name(String、必須)、email(String、必須)、phone(String)、message(String)、property(PropertyへのPointer);objectId、createdAt、updatedAt(システム)。 4. Favorite: user(_UserへのPointer)、property(PropertyへのPointer);objectId、createdAt、updatedAt(システム)。 セキュリティ: - 認証済みユーザーのみがPropertyとFavoriteの作成/更新/削除ができるようACLを設定;Propertyのリストと詳細は公開読み取り可。Lead作成は公開または認証必須に可能。 - Class-Level Permissionsで認証済みユーザーのみがFavoriteを管理;PropertyとLeadは必要に応じて。 認証: - サインアップ(username、email、password)とログイン;ログアウト/セッション対応。 動作: - Property(リスト担当)とFavoriteの完全なCRUD。 - Propertyに紐づくLead(問い合わせ)の作成;物件別または現在のユーザーのリスト別にLeadを一覧。 - ジオクエリ:location(GeoPoint)と$nearSphere、limitでポイント近くの物件を検索。 - status、beds、baths、価格帯、propertyTypeでPropertyをフィルタ。 - オプション:新規リストやお気に入り変更のリアルタイムLive Queries。 成果物: - 上記スキーマ、ACL、必要なCloud CodeでBack4appアプリを作成。 - フロントエンドを生成してこのバックエンドに接続;アプリをエンドツーエンドで実行可能にデプロイ。 フロントエンドにFlutterとBack4app Flutter SDKを使用。物件リスト(ジオ/マップ)、物件詳細、リードフォーム、お気に入り画面を含め、保存したリストのオフラインピニングをサポート。
下のボタンを押して、このテンプレートのプロンプトが事前に入力された状態でエージェントを開きます。
APIプレイグラウンド
不動産スキーマのためにRESTおよびGraphQLエンドポイントを試してください。上記のサンプルデータからのレスポンス — Back4appアカウントは必要ありません。
このテンプレートと同じスキーマを使用します。
ステップバイステップ Flutter 統合
FlutterアプリからBack4appバックエンドに接続し、Back4app Flutter SDKを使用します。
ステップ1: Back4app Flutter SDKをインストール
スタックにBack4app SDKを追加します(例:npm、pubspec、またはパッケージマネージャー)。
YAMLdependencies: flutter: sdk: flutter parse_server_sdk_flutter: ^7.0.0ステップ2:アプリでBack4appを初期化します
アプリの起動時にApp IDとサーバーURLを使用してBack4app SDKを初期化します。
Dartimport 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Parse().initialize( 'YOUR_APP_ID', 'https://parseapi.back4app.com', clientKey: 'YOUR_CLIENT_KEY', autoSendSessionId: true, ); runApp(const MyApp()); }ステップ3:プロパティをクエリします(オプションのジオ付き)
SDKを使用してプロパティオブジェクトを取得します。"近く"または地図結果のためにジオクエリを使用します。
DartFuture<List<ParseObject>> getProperties({String status = 'for_sale'}) async { final query = QueryBuilder<ParseObject>(ParseObject('Property')) ..whereEqualTo('status', status) ..orderByDescending('createdAt'); final response = await query.query(); if (response.success && response.results != null) { return response.results as List<ParseObject>; } return []; } // Geo query: properties near a point Future<List<ParseObject>> getPropertiesNear(double lat, double lng, {int limit = 20}) async { final query = QueryBuilder<ParseObject>(ParseObject('Property')) ..setLocationConstraint('location', ParseGeoPoint(latitude: lat, longitude: lng), 50) ..setLimit(limit); final response = await query.query(); return response.success && response.results != null ? response.results as List<ParseObject> : []; }ステップ4:リード(問い合わせ)を作成します
名前、メール、電話、メッセージ、およびプロパティポインタを使用してリードを作成します。
DartFuture<void> createLead(String name, String email, String propertyId, {String? phone, String? message}) async { final lead = ParseObject('Lead') ..set('name', name) ..set('email', email) ..set('property', ParseObject('Property')..objectId = propertyId); if (phone != null) lead.set('phone', phone); if (message != null) lead.set('message', message); final response = await lead.save(); if (response.success) { print('Lead created: ${response.result.objectId}'); } }ステップ5:お気に入りを管理します
お気に入り(ユーザー + プロパティ)を追加または削除します。現在のユーザーのお気に入りをリストします。
Dart// Add favorite (user + property) Future<void> addFavorite(ParseUser user, String propertyId) async { final favorite = ParseObject('Favorite') ..set('user', user) ..set('property', ParseObject('Property')..objectId = propertyId); await favorite.save(); } // Remove favorite Future<void> removeFavorite(String favoriteId) async { final favorite = ParseObject('Favorite')..objectId = favoriteId; await favorite.delete(); } // List favorites for current user Future<List<ParseObject>> getMyFavorites(ParseUser user) async { final query = QueryBuilder<ParseObject>(ParseObject('Favorite')) ..whereEqualTo('user', user); final response = await query.query(); return response.success && response.results != null ? response.results as List<ParseObject> : []; }
状態管理の統合
アプリの状態層(例:コンテキスト、ストア、またはサービス)に Back4app SDK を統合します。
完全なデータモデル
型安全なシリアル化のために完全なプロパティ/リード/お気に入りモデルをコピーします(例:クラス、インターフェース、または型定義)。
class Property {
final String? objectId;
final String title;
final String? description;
final double? price;
final String? address;
final ParseGeoPoint? location;
final int? beds;
final int? baths;
final double? area;
final String? propertyType;
final String? status;
final String? listedById;
final DateTime? createdAt;
final DateTime? updatedAt;
Property({
this.objectId,
required this.title,
this.description,
this.price,
this.address,
this.location,
this.beds,
this.baths,
this.area,
this.propertyType,
this.status = 'for_sale',
this.listedById,
this.createdAt,
this.updatedAt,
});
factory Property.fromJson(Map<String, dynamic> json) {
return Property(
objectId: json['objectId'] as String?,
title: json['title'] as String,
description: json['description'] as String?,
price: (json['price'] as num?)?.toDouble(),
address: json['address'] as String?,
location: json['location'] != null ? ParseGeoPoint.fromJson(json['location']) : null,
beds: json['beds'] as int?,
baths: json['baths'] as int?,
area: (json['area'] as num?)?.toDouble(),
propertyType: json['propertyType'] as String?,
status: json['status'] as String? ?? 'for_sale',
listedById: json['listedBy'] is Map ? (json['listedBy'] as Map)['objectId'] as String? : null,
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
);
}
}
class Lead {
final String? objectId;
final String name;
final String email;
final String? phone;
final String? message;
final String? propertyId;
final DateTime? createdAt;
final DateTime? updatedAt;
Lead({
this.objectId,
required this.name,
required this.email,
this.phone,
this.message,
this.propertyId,
this.createdAt,
this.updatedAt,
});
factory Lead.fromJson(Map<String, dynamic> json) {
return Lead(
objectId: json['objectId'] as String?,
name: json['name'] as String,
email: json['email'] as String,
phone: json['phone'] as String?,
message: json['message'] as String?,
propertyId: json['property'] is Map ? (json['property'] as Map)['objectId'] as String? : null,
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
);
}
}
class Favorite {
final String? objectId;
final String? userId;
final String? propertyId;
final DateTime? createdAt;
final DateTime? updatedAt;
Favorite({
this.objectId,
this.userId,
this.propertyId,
this.createdAt,
this.updatedAt,
});
factory Favorite.fromJson(Map<String, dynamic> json) {
return Favorite(
objectId: json['objectId'] as String?,
userId: json['user'] is Map ? (json['user'] as Map)['objectId'] as String? : null,
propertyId: json['property'] is Map ? (json['property'] as Map)['objectId'] as String? : null,
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
);
}
}オフラインファースト & ローカルデータストア
pin() と unpin() を使用して、物件とお気に入りをオフラインで利用できるようにし、オンラインに戻ったときに同期します。
サポートされている SDK にはローカルデータストアが含まれています。プロパティとお気に入りオブジェクトをデバイスに保持するためにピン留めし、オフラインのときにピン留めされたデータをクエリします。アプリがオンラインに戻ったとき、サーバーと同期します。
以下:取得後に結果をピン留めし、ローカルコピーが不要になったらアンピンします。
// Pin properties after fetch (offline-first)
Future<void> fetchAndPinProperties() async {
final query = QueryBuilder<ParseObject>(ParseObject('Property'))
..whereEqualTo('status', 'for_sale')
..orderByDescending('createdAt');
final response = await query.query();
if (response.success && response.results != null) {
final results = response.results!.cast<ParseObject>();
await ParseObject.pinAllObjects(results);
// Query from local store when offline:
// QueryBuilder<ParseObject>(ParseObject('Property')).fromLocalDatastore();
}
}
// Unpin when no longer needed
Future<void> unpinAllProperties() async {
await ParseObject.unpinAll('Property');
}よくある質問
不動産リスティングバックエンドテンプレートに関する一般的な質問。