Я знаю, что этой теме уже несколько лет, но я делюсь своим решением для людей, которые все еще ищут ответ (во время моего поиска я оказался здесь).
Обратите внимание, я искал простую функцию, которая давала бы мне вложенные (внешний ключ) объекты / словари (которые также могли содержать вложенные (внешний ключ) объекты / словари) в моей модели / наборе запросов, которые я затем мог бы преобразовать в JSON.
В моем models.py у меня есть пользовательская функция (не в классе модели):
Models.py
def django_sub_dict(obj):
allowed_fields = obj.allowed_fields() # pick the list containing the requested fields
sub_dict = {}
for field in obj._meta.fields: # go through all the fields of the model (obj)
if field.name in allowed_fields: # be sure to only pick fields requested
if field.is_relation: # will result in true if it's a foreign key
sub_dict[field.name] = django_sub_dict(
getattr(obj, field.name)) # call this function, with a new object, the model which is being referred to by the foreign key.
else: # not a foreign key? Just include the value (e.g., float, integer, string)
sub_dict[field.name] = getattr(obj, field.name)
return sub_dict # returns the dict generated
Эта функция перебирает все поля в объекте models.Model, если предоставляется models.Model. Я вызываю функцию в модели следующим образом (для полноты картины, включая одну целую модель):
тот же Models.py
class sheet_categories(models.Model):
id = models.AutoField(primary_key=True, unique=True)
create_date = models.DateField(auto_now_add=True)
last_change = models.DateField(auto_now=True)
name = models.CharField(max_length=128)
sheet_type = models.ForeignKey(
sheet_types, models.SET_NULL, blank=False, null=True)
balance_sheet_sort = models.IntegerField(unique=True)
def allowed_fields(self):
return [
'name',
'sheet_type',
'balance_sheet_sort',
]
def natural_key(self):
return django_sub_dict(self) # call the custom function (which is included in this models.py)
Примечание:
Вложенные объекты JSON будут содержать только те поля, которые включены в allow_fields модели. Таким образом, не включая конфиденциальную информацию.
Чтобы в конечном итоге сгенерировать JSON, в моем views.py есть следующее представление.
views.py
class BalanceSheetData(ListView): # I believe this doesn't have to **be** a ListView.
model = models.sheet_categories
def get_queryset(self):
return super().get_queryset().filter() # the filter is for future purposes. For now, not relevant
def get(self, request, *args, **kwargs):
context = {
'queryset': serializers.serialize("json",
self.get_queryset(),
use_natural_foreign_keys=True, # this or the one below makes django include the natural_key() within a model. Not sure.
use_natural_primary_keys=True, # this or the one above makes django include the natural_key() within a model. Not sure.
),
}
return JsonResponse(context)
Это в конечном итоге дало мне все вложенные детали, которые мне потребовались в ответе JSON. Хотя я не разделяю ответ JSON, так как он едва читаемый.
Не стесняйтесь комментировать.