Двусторонние запросы в Django без циклической ссылки - PullRequest
2 голосов
/ 04 февраля 2011

Допустим, у вас есть две модели: Post и Category. Каждый Post имеет category_id.

Получить категорию сообщения просто: post.category. Что делать, если вы хотите получить все сообщения для определенной категории? Я полагаю, вы бы сделали

def posts(self):
    return Post.filter(category__pk=self.id)

Но что, если модель Post и модель Category находятся в отдельных файлах? Поскольку Post и Category теперь требуют друг друга, вы получите круговую ссылку.

Может быть, вы говорите, что решение состоит в том, чтобы поместить Post и Category в один файл. Но что, если ваше приложение имеет 50 различных моделей, многие из которых довольно большие, все в отдельных файлах? Стоит ли объединить Post и Category в один файл и оставить все остальные отдельно? Стоит ли объединить все 50 моделей в один гигантский файл?

Я надеюсь найти одну из двух вещей:

  1. Ответ на эту проблему, не требующий объединения файлов
  2. Хорошая логическая причина для объединения моделей в один файл друг с другом. Все мои модели в какой-то степени связаны между собой, поэтому, где вы рисуете линию в отношении группировки? Если вы нарисуете линию с внешними ключами, все мои модели окажутся в одном файле.

Ответы [ 2 ]

3 голосов
/ 04 февраля 2011

Для части 1. вашего вопроса:

Django автоматически устанавливает для вас обратную связь.в вашей категории у вас есть доступ к атрибуту post_set, который сам по себе является Manager, поэтому вы можете сделать:

def posts(self):
    return self.post_set.all()

Проверьте документы для получения дополнительной информации по этому вопросу.

Для части 2. У меня есть менее полный ответ ... Если у вас возникла необходимость разбить модели на множество файлов, у вас, вероятно, есть более фундаментальная проблема.Я бы сказал, что вам следует подумать о том, чтобы разбить это огромное приложение на несколько меньших.

Я думаю, что лучший совет, который я получил в плане уменьшения размера моих приложений, - это "сделать одну вещь".Если ваше приложение не может быть описано в относительно короткой фразе, стоит подумать о том, как разбить его на несколько небольших приложений, каждое из которых будет «делать одно».

Конечно, скорее загружен.Требуется немало планирования, чтобы понять, как разбить некоторые сложные задачи, и иногда задним числом является единственным способом увидеть, где вещи вышли из-под контроля.И рефакторинг чего-то такого размера, о котором вы говорите, может быть довольно пугающим.(Если вы можете сказать, что я говорю из опыта!).Мой единственный совет в этом случае - делать шаг за шагом.Попробуйте разбить то, что выглядит как большие, охватывающие приложения проблемы, на небольшие управляемые куски и делать их, когда можете.

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

2 голосов
/ 04 февраля 2011

Вы можете ссылаться на модели по их названию (то есть строке), а не по фактическому объекту. Они в отдельных приложениях? В этом случае вы можете ссылаться на них, используя точечную запись, как описано в документации для ForeignKey :

#in mysite/categories/models.py
class Category(models.Model):
    ...


#in mysite/posts/models.py
class Post(models.Model):
    category = models.ForeignKey('categories.Category')

Вы также можете импортировать модель внутри функции, а не вверху файла. Я часто так делаю, чтобы избежать циклических ссылок:

def posts(self):
    from posts.models import Post
    return Post.filter(category__pk=self.id)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...