Я хочу создать json-файл из моей базы данных Django sqlite3 в качестве резервной копии, а не отображать его на веб-странице.

Я могу получить данные из базы данных sqlite3 и спроецировать их на веб-страницу в формате Json, но у меня возникают проблемы с воспроизведением этого, когда я хочу создать файл. Я новичок в python, Django и работе с базами данных. Я просмотрел и попробовал несколько частей кода, но вся информация, которую я смог найти, относилась к тому, чего я уже достиг, то есть к отображению данных на веб-странице.

Вот как я сейчас использую свой файл views.py для отображения данных на веб-странице.

import json
from django.utils import timezone
from django.db.models import Q
from django.http import JsonResponse
from django.views import View
from chpapi.models import BlockedList


class IPListJsonView(View):
    def get(self, request):

        json_response = {
            "version": "",
            "description": "",
            "objects": [
                {
                    "name": "",
                    "id": "",
                    "description": "",
                    "ranges": ["2.2.2.2"],
                },
            ],
        }

        group_map = {}

        for ip in BlockedList.objects.filter(
            Q(end_date__isnull=True) | Q(end_date__gte=timezone.now())
        ).select_related("group"):
            group_id = str(ip.group.id)
            if group_id not in group_map:
                group_map[group_id] = {
                    "name": ip.group.name,
                    "id": ip.group.group_id,
                    "description": ip.group.description,
                    "ranges": [],
                }
            group_map[group_id]["ranges"].append(ip.address)

        json_response["objects"] = list(group_map.values())

        return JsonResponse(json_response)

Приведенный выше код выдает то, что я хочу, мне приходится опускать некоторые объекты, но в основном четыре столбца, которые я беру из models.py - это название, group_id, описание и ranges - значение IP, которое имеет свое собственное определение, поскольку Django GenericIPAddress не поддерживает некоторые атрибуты, которые я хочу.

Я подумал, что простое исправление с точки зрения генерации файла также (Это в целях безопасности; в случае, если база данных или резервная копия может быть повреждена) было бы просто вставить этот код ниже.

    data = JsonResponse

    with open('test_data.json', 'w') as fp:
        json.dump(data, fp, indent=4)

В итоге получается, что файл создается, но он пустой, и я думаю, что мне придется написать новый класс в представлениях для записи файла. Если возможно, если у кого-то есть статьи или даже решения по извлечению колонок из базы данных Sqlite3 и записи их в файл в формате json, это было бы полезно. Или если возможно включить создание файла в тот же класс views.

Пожалуйста, дайте мне знать, если я не включил достаточно информации, и я отредактирую и улучшу это сообщение.

Вам нужен сериализатор, который преобразует ваши данные в json. Затем вы можете использовать его как в обычном представлении, так и для создания файла.

with open("test_data.json", "w") as out:
    my_json_serializer.serialize(BlockedList.objects.filter(...), stream=out)

Дополнительная информация здесь:

https://docs.djangoproject.com/en/5.0/topics/serialization/#serializing-data

У вас уже есть данные в формате JSON в json_response, так что все, что осталось сделать, это записать эти данные в файл. Поскольку вы не можете полностью положиться на корректность рабочей директории вашего сервера, я бы рекомендовал явно указать директорию для этих дампов в настройках и использовать ее.

from django.conf import settings
import json
import time

# ...

dump_path = os.path.join(settings.DUMPS_DIRECTORY, f"dump-{int(time.time())}.json")
with open(dump_path, "w") as fp:
    json.dump(json_response, fp)

return JsonResponse({"message": f"ok, saved {dump_path}"}) 

С другой стороны, если вы хотите передать данные пользователю, но указать браузеру пользователя, что он должен обрабатывать их как файл, используйте Content-Disposition заголовок, чтобы сказать об этом:

filename = f"dump-{int(time.time())}.json"
response = JsonResponse(json_response)
response["Content-Disposition"] = f"attachment; filename={filename}"
return response
Вернуться на верх