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

StackOverflow https://stackoverflow.com/questions/353571

Вопрос

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

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

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

мойсайт/блог/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()

мойсайт/комментарии/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)  

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ

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

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, но эти модели достаточно близки, чтобы находиться в одном приложении.

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top