File size: 4,691 Bytes
9c79457
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
565008e
 
 
9c79457
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from fastapi import FastAPI, HTTPException
from typing import List, Dict, Optional
import json
import requests
from pydantic import BaseModel

app = FastAPI(title="Vietnam Geographic API",
              description="API để truy xuất thông tin về các đơn vị hành chính của Việt Nam")


# Mô hình Pydantic cho dữ liệu
class Ward(BaseModel):
    name: str


class District(BaseModel):
    name: str
    wards: List[Ward]


class City(BaseModel):
    name: str
    districts: List[District]


# Tải dữ liệu từ URL thay vì file local
def load_geographic_data():
    try:
        # URL dữ liệu từ Hugging Face
        url = "https://huggingface.co/spaces/pmshoanghot/api_tinh_thanh/resolve/main/vietnam-provinces.json"
        response = requests.get(url)

        # Kiểm tra nếu request thành công
        if response.status_code == 200:
            return response.json()
        else:
            raise HTTPException(status_code=500, detail=f"Không thể tải dữ liệu từ URL: Mã lỗi {response.status_code}")

    except requests.RequestException as e:
        raise HTTPException(status_code=500, detail=f"Lỗi khi kết nối đến URL: {str(e)}")
    except json.JSONDecodeError:
        raise HTTPException(status_code=500, detail="File JSON không hợp lệ")


# Tải dữ liệu khi khởi động ứng dụng
geographic_data = load_geographic_data()


# Endpoint gốc
@app.get("/")
async def root():
    return {
        "message": "Chào mừng đến với Vietnam Geographic API. Sử dụng /api/list để lấy danh sách tất cả các tỉnh thành."}


# Lấy danh sách tất cả các tỉnh thành
@app.get("/api/list", response_model=List[Dict[str, str]])
async def get_cities():
    return [{"name": city["name"]} for city in geographic_data]


# Lấy danh sách quận/huyện của một tỉnh/thành phố cụ thể
@app.get("/api/city/{city_name}/districts", response_model=List[Dict[str, str]])
async def get_districts(city_name: str):
    for city in geographic_data:
        if city["name"] == city_name:
            return [{"name": district["name"]} for district in city["districts"]]
    raise HTTPException(status_code=404, detail=f"Không tìm thấy tỉnh/thành phố '{city_name}'")


# Lấy danh sách phường/xã của một quận/huyện cụ thể trong một tỉnh/thành phố
@app.get("/api/city/{city_name}/district/{district_name}/wards", response_model=List[Dict[str, str]])
async def get_wards(city_name: str, district_name: str):
    for city in geographic_data:
        if city["name"] == city_name:
            for district in city["districts"]:
                if district["name"] == district_name:
                    return [{"name": ward["name"]} for ward in district["wards"]]
            raise HTTPException(status_code=404,
                                detail=f"Không tìm thấy quận/huyện '{district_name}' trong tỉnh/thành phố '{city_name}'")
    raise HTTPException(status_code=404, detail=f"Không tìm thấy tỉnh/thành phố '{city_name}'")


# Lấy thông tin chi tiết về một tỉnh/thành phố cụ thể
@app.get("/api/city/{city_name}", response_model=City)
async def get_city_detail(city_name: str):
    for city in geographic_data:
        if city["name"] == city_name:
            return city
    raise HTTPException(status_code=404, detail=f"Không tìm thấy tỉnh/thành phố '{city_name}'")


# Chức năng tìm kiếm (tìm theo tên một phần)
@app.get("/api/search", response_model=List[Dict[str, str]])
async def search(q: str, type: Optional[str] = "city"):
    results = []

    if type == "city":
        results = [{"name": city["name"]} for city in geographic_data
                   if q.lower() in city["name"].lower()]

    elif type == "district":
        for city in geographic_data:
            for district in city["districts"]:
                if q.lower() in district["name"].lower():
                    results.append({
                        "name": district["name"],
                        "city": city["name"]
                    })

    elif type == "ward":
        for city in geographic_data:
            for district in city["districts"]:
                for ward in district["wards"]:
                    if q.lower() in ward["name"].lower():
                        results.append({
                            "name": ward["name"],
                            "district": district["name"],
                            "city": city["name"]
                        })

    return results


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)