Новичок: попытка понять, как приложения взаимодействуют в Django

Я только что закончил работу с учебниками Django во второй раз, и теперь я понимаю вещи намного яснее. Тем не менее, я все еще не понимаю, как приложения внутри сайта взаимодействуют друг с другом.

Например, скажем, я пишу приложение для блога (довольно популярная деятельность, видимо). Сообщения в блогах и комментарии, как правило, идут вместе, и все же они достаточно отчетливы, что их нужно встроить в отдельные приложения, а также общую философию развития Djano.

Рассмотрим следующий пример. На самом деле я бы на самом деле не писал приложение комментариев, поскольку хороший код для этого уже существует в Интернете, но это для демонстрационных/практических целей:

MySite/блог/models.py

from django.db import models

class post(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=200)
    content = models.TextField()

MySite/комментарии/models.py

from django.db import models
from mysite.blog.models import post

class comment(models.Model):
    id = models.AutoField()
    post = models.ForeignKey(post)
    author = models.CharField(max_length=200)
    text = models.TextField()

Это то, что я написал выше, импортируя модель из другого приложения и устанавливая ее как внешний ключ, как взаимодействуют приложения Django? Или есть другой/лучший метод для приложений, которые содержат сайт для взаимодействия?

Обновление
По рекомендации в одном ответе я читаю документацию для contrib.contenttypes. Если я правильно это прочитал, я мог бы переписать свое приложение комментариев к примеру следующим образом:

from django.db import models  
from django.contrib.contenttypes.models import ContentType
from django.contrib.contentypes import generic

class comment(models.Model):  
    id = models.AutoField()  
    author = models.CharField(max_length=200)  
    text = models.TextField()  
    content_type = models.ForeignKey(ContentType)  
    content_object = generic.GenericForeignKey(content_type, id)  

Правильно ли это?

Ответ 1

Взгляните на встроенный django структура контента:

django.contrib.contenttypes

Это позволяет вам разрабатывать приложения как автономные. Это то, что разработчики django использовали для создания django встроенной рамки комментариев для добавления комментария к любой модели в вашем проекте.

Например, если у вас есть какой-либо объект контента, который вы хотите "прикрепить" к другим объектам контента разных типов, например, чтобы каждый пользователь оставил "любимую" звезду в блоге, изображении или профиле пользователя, вы может создать модель Favorite с общим полем отношения следующим образом:

from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Favorite(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

Таким образом, вы можете добавить звездочку Favorite от любого пользователя к любой модели вашего проекта. Если вы хотите добавить доступ к API через класс модели получателя, вы можете либо добавить обратное отношение общих полей в модель получателя (хотя это будет "связать" две модели, которые, как вы сказали, вы хотели избежать), или выполнить поиск по модели Favorite с помощью content_type и object_id экземпляра получателя, см. официальные документы для примера.

Ответ 2

"Это то, что я написал выше, импортируя модель из другого приложения и устанавливая ее как внешний ключ, как взаимодействуют приложения Django?"

Угу. Работает для меня.

У нас есть около 10 приложений, которые занимают между собой.

Это приводит к некоторой зависимости в нашем unit test script.

Это выглядит так.

  • "собственность". У нас есть простое приложение для владения данными, которое определяет некоторые основные концепции владения, от которых зависят другие приложения. Здесь есть несколько простых таблиц.

  • "вещь". [Не настоящее имя]. Наше приложение имеет элементы данных, принадлежащие различным группам пользователей. На самом деле существует несколько сложных таблиц модели для этого приложения. Это зависит от "собственности".

  • "таблицы". [Не настоящее имя]. Некоторые из наших пользователей создают довольно сложные автономные модели (возможно, с электронными таблицами) и загружают результаты этого моделирования в "таблицы". Это кластер довольно сложных таблиц. Это зависит от "собственности".

  • "результат"

    . [Не настоящее имя]. Наши результаты основаны на вещах, имеющих владельцев. Результаты основаны на вещах и таблицах и являются ответами на запросы клиентов. Это не слишком сложно, возможно, только две или три основные таблицы. Это зависит от "вещей" и "стола". Нет, это не полностью автономно. Тем не менее, он подвержен большим изменениям, чем другие вещи, от которых это зависит. Вот почему он разделяется.

  • "обработка". Мы планируем и контролируем большие пакетные задания. Это в этом приложении. Он действительно общий и может использоваться различными способами. Он полностью стоит один.

  • "Добро пожаловать". У нас есть приложение "добро пожаловать", которое представляет собой кучу в основном статических страниц. Это не слишком много таблиц. Но это на нем второе воплощение, потому что первое было слишком сложным. Он полностью стоит один.

Единственное соотношение между зависимыми приложениями - это некоторые имена таблиц. Пока мы сохраняем эти таблицы (и их ключи), мы можем упорядочить другие приложения по своему усмотрению.

Ответ 3

Нет ничего плохого (imho) с тем, чтобы приложение зависело от другого. В конце концов, приложения - это всего лишь операции над набором моделей. вам просто нужно всегда знать, какое приложение зависит от того, какое приложение (я думаю, вы могли бы назвать эту карту зависимостей).

Вы можете достичь свободной связи с базой содержимого. Это приложение может быть действительно портативным/подключаемым, но все же интегрированным с другими приложениями.

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

Предположим, вы хотите, чтобы модельный поток был подключен к любой другой модели. Идея состоит в том, чтобы создать общий ключ (см. Документацию по django) и написать небольшую функцию, которая принимает любой объект и возвращает соответствующий ему поток (или создает его, если это необходимо), и писать собственный тег шаблона, который использует эту функциональность, например {% get_thread for arbitrary_object as thread %}. Все сообщения относятся к потоку, который связан с объектом, который может быть любого типа.

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

ИЗМЕНИТЬ

Здесь вы можете создать общий внешний ключ с картой типов контента:

from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType

class Thread( models.Model ):
    object_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    object = generic.GenericForeignKey('object_type', 'object_id')

Вы можете сделать его более "прозрачным", используя неявный "общий" интерфейс, который django предполагает, что все объекты реализуются.

    #inside the Thread class:
    def __unicode__(self):
        return unicode(self.object)
    def get_absolute_url(self):
        return self.object.get_absolute_url()

Ответ 4

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

Как разделить проект

Я бы отделил приложение, если:

  • Я планирую его создать. (и попробуйте свободное соединение)
  • (для крупных проектов) Он состоит из основного раздела проекта.

С другой стороны; имея много маленьких приложений (например, приложение с одной моделью и двумя видами), трудно читать и поддерживать IMHO.

Как приложения должны взаимодействовать

Это зависит от типа проекта и типа приложения. Например, если приложение неявно зависит от другого (т.е. Не общего), то импорт и использование ссылок из другого приложения являются приемлемыми. В этом случае второе приложение может быть установлено отдельно, но для первого требуется наличие второго.

Если вы хотите сделать приложение очень многоразовым и универсальным, например приложение для комментариев, вам может понадобиться интегрировать некоторые механизмы установки. Возможно, некоторые новые настройки или дополнительная конфигурация URL или специальная директива/метод для ваших моделей... django.contrib.admin - хороший пример для этого.

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