Я использую Django и у меня есть несколько вариантов использования, для которых требуется возможность для объектов отслеживать свои отношения через несколько моделей. Я не хочу вручную кодировать эту функциональность для каждой модели. Некоторые примеры моделей:
class Project(models.Model):
project_name = models.CharField(max_length=200, default="development_project")
class Question(models.Model):
project = models.ForeignKey(Project, default=1, on_delete=models.CASCADE)
question_text = models.CharField(max_length=200, default="question text")
class Extra(models.Model):
extended_q = models.ForeignKey(Question, default=1, on_delete=models.CASCADE)
summary_of = models.ForeignKey(Question, default=1, on_delete=models.CASCADE)
content = models.CharField(max_length=200, default="simple summary")
class Answer(models.Model):
question = models.ForeignKey(Question, default=1, on_delete=models.CASCADE)
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)
Использование моделей в качестве узлов сети и отношений в качестве ребер, кажется, что это должно быть управляемым, но для некоторой сложности, где есть «избыточные» ребра - мы разрешаем дополнительный суммировать ответы из другого проекта?
мои варианты использования будут:
- класс models.Manager, который может выступать в качестве менеджера по умолчанию для подкласса Django приложения, которые работают вместе на едином сайте и помогают осуществлять управление разделением строк, которое не позволит пользователям, даже администраторам, оказаться под ногами друг друга.
- общее приложение, использующее ContentTypes, которое может помочь Пользователь создает наборы данных и организует таблицы для фреймов данных (принимая fks и присваивая им соответствующие переменные категории и т. д. c).
Django предоставляет очень хорошие дескрипторы от одной модели к другой, поэтому я пытаясь использовать эти свойства в очень маленькой функции, полученной из find_all_paths: python паттернов, эссе
def fap(start, goal, path=[]):
path = path + [start]
if start == goal:
return path
paths = []
neighbour_list = [fk for fk in start._meta.get_fields() \
if (fk.concrete and fk.many_to_one and not fk.remote_field.model == start)]
for neighbour in neighbour_list:
if neighbour not in path:
path.append(neighbour)
newpaths = fap(neighbour.remote_field.model, goal, path)
for newpath in newpaths:
paths.append(newpath)
return [paths]
Результаты:
> h = fap(e,a)
> h
[[
[<class 'polls.models.Extra'>, <django.db.models.fields.related.ForeignKey: extended_question>, <class 'polls.models.Question'>, <django.db.models.fields.related.ForeignKey: project>, <class 'polls.models.Project'>],
[<class 'polls.models.Extra'>, <django.db.models.fields.related.ForeignKey: extended_question>, <django.db.models.fields.related.ForeignKey: summary_of>, <class 'polls.models.Question'>, <django.db.models.fields.related.ForeignKey: project>, <class 'polls.models.Project'>]
]]
Это близко, но если вы посмотрите на второй список, он содержит оба поля FK от Extra до Question. Учитывая, что первый список содержит только «extended_question», было бы неплохо, если бы второй список содержал только «summary_of», но, честно говоря, после того, как вы поразительно долго ткнули в это, я выхожу пустым. Второй список создается первым, и его можно было бы использовать, если бы он был единственным результатом - мне просто нужно было бы интерпретировать список (который будет чередовать модель / поле / модель / поле для одного пути, а двойные поля означают избыточные ребра); но тогда первый список, который содержит только extended_question, плох, потому что 'extended_question' уже был во втором списке, когда он был создан.
Есть ли кусок 1030 *, который я пропустил, или что-то явно неработающее о создании списка с узлами и ребрами?