feat: Refactor outlets with multilingual support and dynamic queries
- Replace static articles array with dynamic source_keyword queries
- Use MongoDB _id as unique identifier for outlets
- Add multilingual translations (9 languages: ko, en, zh_cn, zh_tw, ja, fr, de, es, it)
- Add OutletService for database operations
- Add outlet migration script with Korean source_keyword matching
- Remove JSON file-based outlet loading
- Add /outlets/{outlet_id}/articles endpoint for dynamic article retrieval
This resolves the design issues with:
1. Static articles array requiring constant updates
2. Lack of multilingual support for outlet names/descriptions
3. Broken image URLs
4. Korean entity matching for article queries
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
47
services/news-api/backend/app/models/outlet.py
Normal file
47
services/news-api/backend/app/models/outlet.py
Normal file
@ -0,0 +1,47 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional, Dict
|
||||
|
||||
class OutletTranslations(BaseModel):
|
||||
ko: Optional[str] = None
|
||||
en: Optional[str] = None
|
||||
zh_cn: Optional[str] = None
|
||||
zh_tw: Optional[str] = None
|
||||
ja: Optional[str] = None
|
||||
fr: Optional[str] = None
|
||||
de: Optional[str] = None
|
||||
es: Optional[str] = None
|
||||
it: Optional[str] = None
|
||||
|
||||
class OutletBase(BaseModel):
|
||||
source_keyword: str # Used to query articles dynamically
|
||||
category: str # people, topics, companies
|
||||
name_translations: OutletTranslations = Field(default_factory=lambda: OutletTranslations())
|
||||
description_translations: OutletTranslations = Field(default_factory=lambda: OutletTranslations())
|
||||
image: Optional[str] = None
|
||||
|
||||
# Deprecated - kept for backward compatibility during migration
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
class OutletCreate(OutletBase):
|
||||
pass
|
||||
|
||||
class OutletUpdate(BaseModel):
|
||||
source_keyword: Optional[str] = None
|
||||
category: Optional[str] = None
|
||||
name_translations: Optional[OutletTranslations] = None
|
||||
description_translations: Optional[OutletTranslations] = None
|
||||
image: Optional[str] = None
|
||||
|
||||
# Deprecated
|
||||
name: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
articles: Optional[List[str]] = None
|
||||
|
||||
class Outlet(OutletBase):
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
class OutletList(BaseModel):
|
||||
outlets: List[Outlet]
|
||||
total: int
|
||||
Reference in New Issue
Block a user