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

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

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

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

mysite/blog/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/comments/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)  

будет ли это правильно?

4 ответов


взгляните на встроенный в django contenttypes framework:

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 экземпляра получателя см. официальные документы для примера.


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

да. Работать на меня.

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

Это приводит к своего рода зависимости в нашем сценарии модульного тестирования.

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

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

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

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

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

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

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

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


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

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

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

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

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

редактировать

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

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()

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

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

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

  • я планирую разработать его resuable. (и попробуйте свободную муфту)
  • (для больших проектов) состоит из основного раздела проект.

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

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

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

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

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