Рекомендации по проектированию API: стоит ли структурировать запрос SQL SELECT как json с использованием json_build_object - PullRequest
1 голос
/ 06 мая 2020

Я разрабатываю веб-приложение, которое реализует следующее:

  1. PostgreSQL СУБД без ORM базы данных
  2. Django Rest Framework для проектирования и обработки сериализаторов данных и запросы API в бэкэнде
  3. для методов GET, создайте запрос SQL SELECT, чтобы он имел структуру, подобную json, используя json_build_object

IN DATABASE

person(personid, fullname, cityid)
city(cityid, cityname, countryid)
country(countryid, countryname)

В СЕРИАЛИЗАТОРЕ

class CountrySerializer(serializers.Serializer):
 id=serializers.IntegerField()
 name=serializers.CharField()

class CitySerializer(serializers.Serializer):
 id=IntegerField()
 name=CharField()
 country=CountrySerializer()

class PersonSerializer(serializers.Serializer):
 id=IntegerField()
 person=CharField()
 city=CitySerializer()

В ВИДЕ API

from .custom_utils import raw_sql_select

class APIView_Person(generics.GenericAPIView):
  serializer_class = PersonSerializer
  permission_classes = (IsAuthenticatedOrReadOnly,)
  def get_queryset(self):
   query=("""
    SELECT
     p.personid as id,
     p.fullname as person,
     json_build_object(
      'id',ct.cityid,
      'name',ct.cityname,
      'country',json_build_object(
        'id',cntry.countryid,
        'name',cntry.countryname
       )
     ) AS city
     FROM persons p
     JOIN city ct ON ct.cityid=p.cityid
     JOIN country cntry ON cntry.countryid=ct.countryid
   """)
   return raw_sql_select(query, "db_connection")

  def get(self, request):
   rows = [
    {
      "id": col.id,
      "person": col.person,
      "city": col.city
    } for col in self.get_queryset()[1]
   ]
   results = PersonSerializer(rows, many=True).data
   return Response(results or [])

В ФРОНТЕНДЕ

const [state, setState] = useState({
 personList: []
})

useEffect(()=>{
  fetch('/api/persons/', {method: 'GET', headers:{'Content-Type':'application/json'}})
  .then(res=>res.json())
  .then(rows=>setState(states=>({...states,personList:rows})))
}, [])

return(
 <>
  <Typography variant="body1" component="p">{state.person}</Typography>
  <Typography variant="caption" component="p" color="textSecondary">{state.city}, {state.city.country} 
  </Typography>
 </>
)

Так мой API в настоящее время разработан.

  1. Почему я использую необработанный запрос sql? Поскольку я использую базу данных, которая не создана в моем приложении Django, у меня нет моделей для реализации ORM Django.
  2. Почему мой запрос структурирован как json? Поскольку я использую сериализатор, который не зависит от модели и не расширяет класс ModelSerializer.

Мои вопросы:

  1. Это хороший, приемлемый подход ?
  2. Будет ли такая конструкция создавать в будущем проблему с точки зрения ремонтопригодности в случае изменения структуры базы данных?
  3. Если я изменю CountrySerializer () с name = CharField () на country_name = CharField ( ), а затем измените мой логический интерфейс API c, чтобы он возвращал ключ объекта ответа с 'name' на 'country_name', и у меня есть 20 модулей внешнего интерфейса, которые ссылаются на старый ключ объекта 'name' - тогда, вероятно, мне пришлось бы отредактируйте эти 20 модулей внешнего интерфейса, чтобы изменить ссылку «name» на «country_name». Является ли этот тип обслуживания неизбежным и считается ли этот тип обслуживания частым возможным столкновением в RESTFul API?
...