Разрешение имен всех связанных с Django моделей при экспорте таблицы в текстовый файл (csv)
У меня есть простая таблица Django (4.1/Python3.9) с текстовыми и числовыми полями.
В этой таблице четыре из них ForeignKeys:
1 ссылается сам на себя
1 ссылается на другую таблицу через отношение OneToMany (aka простой ForeignKey)
>>
2 ссылается на 2 другие таблицы через отношение ManyToMany
Django достаточно любезен, когда использует метод model._meta.get_fields()
, чтобы получить все связанные поля вместе с обычными полями модели. И это то, что мне нужно.
На странице администратора этой модели я могу видеть все эти связанные поля как "разрешенные", например, их название отображается вместо их идентификаторов, это происходит из-за обычного метода __str__(self)
, который мы можем использовать в классах модели:
from django.db import models
class Foo(models.Model):
name = model.CharFields(
max_length=100, unique=True, verbose_name="Foo name"
)
# here are some other usual data fields
self_relation = models.ForeignKey(
"self", on_delete=models.CASCADE, null=True, blank=True
)
bar = models.ForeignKey(
"Bar", on_delete=models.CASCADE, null=True, blank=True
)
baz = models.ManyToManyField(Baz)
qux = models.ManyToManyField(Qux)
def __str__(self):
return self.name
class Bar(models.Model):
name = model.CharFields(
max_length=100, unique=True, verbose_name="Bar name"
)
# ...
def __str__(self):
return self.name
class Baz(models.Model):
name = model.CharFields(
max_length=100, unique=True, verbose_name="Baz name"
)
# ...
def __str__(self):
return self.name
class Qux(models.Model):
name = model.CharFields(
max_length=100, unique=True, verbose_name="Qux name"
)
# ...
def __str__(self):
return self.name
Но при попытке экспортировать данные таблицы в текстовый файл с помощью специального маршрута, они не разрешаются автоматически; экспортируются только идентификаторы связанных полей. Что делает этот экспорт трудночитаемым, если только человек не знает в совершенстве соответствие между идентификаторами и именами всех связанных моделей (это невозможно с человеческой точки зрения, когда модели становятся немного сложными).
<from django.http import HttpResponse
import csv
from .models import Foo, Bar, Baz, Qux
def to_comma_separated_file(model, filename):
response = HttpResponse()
response['Content-Disposition'] = f'attachment; filename={filename}.csv'
writer = csv.writer(response)
model_fields = [
f for f in model._meta.get_fields(
include_parents=True,
include_hidden=False
)
]
model_fields_names = [f.name for f in model_fields]
# write the headers:
writer.writerow(model_fields_names)
<
Итак, этот кусок кода следует, в том же views.py
файле:
columns = dict()
# Loop over the columns to check if a field is a relation or not:
for f in model_fields:
columns[f.name] = f.is_relation # this tells me if a field is a foreignkey
# Loop over the rows to replace id by their names in the relation fields:
for row in objects.values(*model_fields_names): # cannot use model_fields here.
for k,v in row.items():
if columns[k]:
new_value = model.objects.get() # <- put intelligence here.
row[k] = new_value
# write each row of data to the file
writer.writerow(row)
<
<
Вы видите, как я могу этого достичь?
<