Как правильно прописать json структуру в models.py проекта django с помощью JSONField?
БД моего проекта — MongoDB, для соединения mongo и проекта django (использую версию 4.0.1) я использую движок «djОngo». Соединение с базой работает корректно.
Я хочу хранить в MongoDB данные, получаемые из внешнего API либо записанные через форму на странице сайта, которые могут иметь вложенные списки, или иногда вложенные объекты.
Пример json структуры которая будет записываться через форму и приходить по API:
"FormsID": 1, "make": < "1_new": 21, "2_new": 16, "right": 80, "left": 10, >, "static": [ < "name": " 1", "number": 1, "id":93, "day": < "start": 7, "end": 23,>>]
На данный момент задача реализована частично, объясняю. Мой файл models.py:
from djongo import models class StaticForms(models.Model): FormsID=models.ObjectIdField(primary_key=True) make = models.JSONField() static=models.JSONField() day=models.JSONField()
Далее уже в файле views.py я добавляю нужные ключи уже в make, static и day.
Мой файл views.py:
from django.views.decorators.csrf import csrf_exempt from django.http.response import JsonResponse, HttpResponse from FirstApp.models import StaticForms @csrf_exempt def forms_post(request): make = static = day = post = StaticForms(FormsID=request.POST.get("FormsID"), make=make, static=static, day=day) post.save() return HttpResponse("Inserted")
После добавления данных через Postman я получаю следующую JSON структуру. (отличается от требуемой):
"make": < "1_new": 21, "2_new": 16, "right": 80, "left": 10, >, "static": < "name": " 1", "number": 1, "id":93>"day":
1) Как мне вложить dict «day» в dict «static» чтобы получилось, как в моем первом примере?
2) почему отсутствует поле «FormsID»?
- Вопрос задан более года назад
- 191 просмотр
JSONField и кириллица в django
Это безопасный формат. Так url в вебе формируют, в отличие от iri, в котором разрешён utf-8. Только если переопределять и допиливать сам jsonfield. Можно просто обратную конвертацию сделать.
1 июн 2017 в 18:14
Не работайте с json на прямую. Есть хорошие варианты редакторов для таких полей. По вопросу. Это стандарт для json, если его не нарушать, то никак. Если преобразуете, то в базе у вас уже будет храниться не json, а что-то похожее.
1 июн 2017 в 18:30
@Igor стандарт для JSON — UTF-8, выводить кириллицу (и другие нетехнические символы) как есть вполне разрешает RFC 7159
4 июн 2017 в 9:54
@andreymal, согласен. Но в стандарте так же указано, что необходимо для совместимости. По редакторам, возможно использовать например github.com/paytm/dj-j-ka-bachcha-field, чтобы не полностью руками редактировать.
5 июн 2017 в 0:28
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
import json from pygments import highlight from pygments.lexers import JsonLexer from pygments.formatters import HtmlFormatter from django.contrib import admin from django.utils.safestring import mark_safe from .models import Some @admin.register(Some) class SomeAdmin(admin.ModelAdmin): fields = ('items_prettified',) readonly_fields = ('items_prettified',) def items_prettified(self, instance): # Преобразуем данные поля в юникод-строку с отступами json_str = json.dumps(instance.items, sort_keys=True, indent=2, ensure_ascii=False) # Обрезаем, если строка слишком длинная json_str = json_str[:5000] # Добавляем подсветку синтаксиса formatter = HtmlFormatter(style='colorful') output = highlight(json_str, JsonLexer(), formatter) style = "
" return mark_safe(style + output) items_prettified.allow_tags = True items_prettified.short_description = Some._meta.get_field('items').verbose_name.title()
Отслеживать
ответ дан 4 июн 2017 в 8:52
Sergey Gornostaev Sergey Gornostaev
66.3k 6 6 золотых знаков 51 51 серебряный знак 112 112 бронзовых знаков
Можно воспользоваться предыдущим решением, но тогда у нас будет два поля в админке: одно с кириллицей, второе в кодировке. Я нашел такое решение:
- Создаём файл utils.py в папке с приложением и вставляем в него следующее:
import json from django.contrib.postgres.forms.jsonb import InvalidJSONInput, JSONField class ReadableJSONFormField(JSONField): def prepare_value(self, value): if isinstance(value, InvalidJSONInput): return value return json.dumps(value, ensure_ascii=False, indent=4)
- Заходим в admins.py и «перезаписываем» поле.
from django.contrib import admin from django.contrib.postgres.fields import JSONField from .utils import ReadableJSONFormField from .models import Some @admin.register(Some) class SomeAdmin(admin.ModelAdmin): formfield_overrides = < JSONField: , >
Желательно именно прописывать ReadableJSONFormField в utils.py, тк если прописать в админке его, то не у меня работает через раз.
О Python с Игорем Давыденко
Всякое разное о Python, раньше было про Django/Flask, сейчас больше про Fast Python и asyncio.
13 февраля 2009 г.
Простой и работающий JSONField для Django
Не успел, я починить PickleField для Django, мне понадобилось создать JSONField . Задача оказалась решенной на раз/два, плюс ко всему добавился маленький и полезный виджет для JSONField ‘а, который показывает красиво отформатированный JSON в textarea . Сразу скажу, что contribute_to_class метод чуть менне, чем полностью, скопипастен с снипетта 377.
from django.conf import settings from django.forms.widgets import Textarea from django.db.models import SubfieldBase, TextField from django.utils import simplejson class JSONField(TextField): __metaclass__ = SubfieldBase def contribute_to_class(self, cls, name): super(JSONField, self).contribute_to_class(cls, name) def get_json(model): return self.get_db_prep_value(getattr(model, self.attname)) setattr(cls, 'get_%s_json' % self.name, get_json) def set_json(model, json): setattr(model, self.attname, self.to_python(json)) setattr(cls, 'set_%s_json' % self.name, set_json) def formfield(self, **kwargs): kwargs['widget'] = JSONWidget(attrs=) return super(JSONField, self).formfield(**kwargs) def get_db_prep_value(self, value): return simplejson.dumps(value) def to_python(self, value): if not isinstance(value, basestring): return value try: return simplejson.loads(value, encoding=settings.DEFAULT_CHARSET) except ValueError, e: # If string could not parse as JSON it's means that it's Python # string saved to JSONField. return value class JSONWidget(Textarea): """ Prettify dumps of all non-string JSON data. """ def render(self, name, value, attrs=None): if not isinstance(value, basestring) and value is not None: value = simplejson.dumps(value, indent=4, sort_keys=True) return super(JSONWidget, self).render(name, value, attrs)
Ну и пару примеров использования, напоследок:
>>> # Пусть у нас есть простая модель >>> class Sample(models.Model): . name = models.CharField(max_length=16) . data = JSONField() >>> # Создадим модель и сохраним в data поле настройки для ShadowBox >>> sb = Sample.objects.create(name='ShadowBox', . data=) >>> # Теперь мы хотим напечатать эти настройки где-то в шаблоне >>> sb.get_data_json() '' >>> # Вспомним, что нам вообщем-то не зачем кастомное значение для overlayOpacity >>> del sb.data['overlayOpacity'] >>> sb.save() >>> # И опять напечатаем настройки в шаблоне >>> sb.get_data_json() ''
зы. ShadowBox — это лучший лайтбокс для любого JavaScript фреймворка, имо.
Простой и работающий JSONField для Django
Не успел, я починить PickleField для Django, мне понадобилось создать JSONField . Задача оказалась решенной на раз/два, плюс ко всему добавился маленький и полезный виджет для JSONField ‘а, который показывает красиво отформатированный JSON в textarea . Сразу скажу, что contribute_to_class метод чуть менне, чем полностью, скопипастен с снипетта 377.
from django.conf import settings from django.forms.widgets import Textarea from django.db.models import SubfieldBase, TextField from django.utils import simplejson class JSONField(TextField): __metaclass__ = SubfieldBase def contribute_to_class(self, cls, name): super(JSONField, self).contribute_to_class(cls, name) def get_json(model): return self.get_db_prep_value(getattr(model, self.attname)) setattr(cls, 'get_%s_json' % self.name, get_json) def set_json(model, json): setattr(model, self.attname, self.to_python(json)) setattr(cls, 'set_%s_json' % self.name, set_json) def formfield(self, **kwargs): kwargs['widget'] = JSONWidget(attrs=) return super(JSONField, self).formfield(**kwargs) def get_db_prep_value(self, value): return simplejson.dumps(value) def to_python(self, value): if not isinstance(value, basestring): return value try: return simplejson.loads(value, encoding=settings.DEFAULT_CHARSET) except ValueError, e: # If string could not parse as JSON it's means that it's Python # string saved to JSONField. return value class JSONWidget(Textarea): """ Prettify dumps of all non-string JSON data. """ def render(self, name, value, attrs=None): if not isinstance(value, basestring) and value is not None: value = simplejson.dumps(value, indent=4, sort_keys=True) return super(JSONWidget, self).render(name, value, attrs)
Ну и пару примеров использования, напоследок:
>>> # Пусть у нас есть простая модель >>> class Sample(models.Model): . name = models.CharField(max_length=16) . data = JSONField() >>> # Создадим модель и сохраним в data поле настройки для ShadowBox >>> sb = Sample.objects.create(name='ShadowBox', . data=) >>> # Теперь мы хотим напечатать эти настройки где-то в шаблоне >>> sb.get_data_json() '' >>> # Вспомним, что нам вообщем-то не зачем кастомное значение для overlayOpacity >>> del sb.data['overlayOpacity'] >>> sb.save() >>> # И опять напечатаем настройки в шаблоне >>> sb.get_data_json() ''
зы. ShadowBox — это лучший лайтбокс для любого JavaScript фреймворка, имо.
Django JSONField: руководство по эффективной обработке данных
Новое поле JSONField в Django позволяет вам использовать JSON в любой базе данных, даже если база данных изначально не поддерживает JSON.
Django автоматически преобразует данные JSON в объект словаря, упрощая взаимодействие с данными и манипулирование ими.
При использовании JSONField в Django важно обеспечить согласованность передаваемых данных для поддержания структуры и целостности базы данных.
Хранение пользовательских настроек в виде объекта JSON в базе данных может быть более эффективным и удобным способом загрузки и извлечения данных конфигурации для интерфейсного приложения.
Summarize any YouTube video by yourself
Desktop options: Safari Chrome
Summarize any YouTube video by yourself
Other options: iOS App Chrome
Summarize any YouTube video by yourself