Новичку в Django трудно работать с моделями и бизнес-логикой многократного использования

#python #django

#python #django

Вопрос:

Я разработчик .net, привыкший работать с asp.net фреймворк mvc и я пытаюсь познакомиться с миром python, в частности, пытаюсь закодировать некоторые веб-сайты с использованием django, но мне трудно разобраться в структуре django.

В asp.net mvc, я использую asp.net mvc framework просто как уровень представления, моя бизнес-логика и мой уровень данных независимы. Это базовая структура всех моих asp.net сайты на mvc:

введите описание изображения здесь

Веб-сайт является asp.net проект mvc, в то время как проекты бизнес-логики и типов данных являются библиотеками классов (dll). В проекте business logic я использую модель entity framework (со всеми классами, которые она генерирует) и создаю несколько классов, которые я называю «Менеджерами», которые содержат основную логику системы. Например, если веб-сайт предназначен для веб-сайта блога, «UsersMgr» будет содержать следующие операции «registerUser, getUser, ConfirmUserAccount», а «PostsMgr» будет содержать операции «AddPost, RemovePost, EditPost, AddComentToPost и т.д.».

Идея этого подхода заключается в том, что веб-сайт — это просто уровень представления, который использует бизнес-логику, но не тесно связан с ней. Обычно я добавляю «Консоль администратора» (другой asp.net веб-сайт mvc для администраторов), «Отчеты для какого-либо партнера» (например, представьте, что в блоге есть реклама, и мы даем партнерам логин, чтобы они могли обновлять свои объявления и видеть отчеты о том, сколько раз показывалась реклама и т.д.), «rest api», чтобы, если я хочу создать мобильное приложение, я мог предоставить бизнес-логику через rest API, cron для выполнения задач сопровождения или отчеты, которые будут отправляться мне по электронной почте в конце каждого дня, и т.д.

В моих проектах .net с предыдущей архитектурой добавление этих новых элементов выглядит следующим образом:

введите описание изображения здесь

По сути, все эти новые добавленные элементы являются «потребителями» бизнес-логики.

Мне трудно понять, как достичь чего-то подобного с помощью django, потому что веб-приложения кажутся действительно тесно связанными со своими моделями, которые являются отображениями в таблицах db. Итак, куда мне поместить бизнес-логику, если я захочу повторно использовать ее позже на веб-сайте, отличном от django?

Что касается приложений django, я повсюду читал, что неплохо разделить веб-сайт в приложениях django, но как вы это делаете, когда обычно концепции связаны. Например, в блоге могут быть пользователи, сообщения, комментарии, теги и т.д. Моя проблема в том, что все связано вместе, сообщения принадлежат пользователю, теги и комментарии связаны с сообщением. Что вы делаете с этими отношениями?

Я был бы очень признателен, если бы кто-нибудь мог мне помочь с этим, я написал несколько скриптов на python для своего raspberry pi, и это выглядит как потрясающий язык, но мне трудно с django. Должно быть что-то, чего мне не хватает…

Спасибо!

Ответ №1:

Представления и модели

Модели являются эквивалентом вашего компонента типов данных. Представления эквивалентны части веб-сайта и обычно содержат код, который содержали бы ваши «Менеджеры».

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

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

Ничто не мешает вам создать слой менеджера между вашими представлениями и вашими моделями, что-то вроде:

models.py:

 class Post(models.Model):
    ...

class Comment(models.Model):
    user = models.ForeignKey(User)
    post = models.ForeignKey(Post)
    text = models.CharField(...)
  

managers.py:

 class PostManager(object):
    @staticmethod
    def getPost(id):
        return Post.object.get(pk=id)

    @staticmethod
    def addComment(post, comment_text, user):
        comment = Comment(post=post, user=user, text=comment_text)
        # check stuff
        comment.save()
    ...
  

views.py:

 def add_comment(request, post_id):
    ...
    PostManager.addComment(post=PostManager.getPost(post_id),
                           user=request.user,
                           request.POST['text'])
    ...
  

Но у этого есть несколько недостатков:

  • API экземпляра модели по-прежнему доступен для обхода таких проверок
  • Вы теряете выразительную силу model API
  • Это несколько чрезмерно многословно

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

Приложения Django

Это хорошая идея разделить вещи на приложения. Приложения должны быть разделены по функциональным линиям, разделяя различные функции, которые выполняет ваш проект в целом.

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

Неплохо, что приложение blog зависит от пользовательского приложения, имеет смысл использовать существующую функциональность в приложении blog, которую предоставляет пользовательское приложение.

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

Ответ №2:

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

Django также продвигает использование моделей fat и менеджеров. Менеджеры в Django могут в какой-то момент занять место контроллеров MVC, потому что их работа заключается в работе с коллекциями экземпляров модели. Однако вы можете расширить model manager, чтобы приспособить инструкции, к которым вы привыкли.

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

Приложение администратора встроено в Django, и его действительно легко настроить в соответствии с вашими потребностями.

Говоря об интерфейсах, представления Django — это просто интерфейс. Это не говорит вам, как вы должны представлять свои данные. В Django есть очень мощный фреймворк шаблонов, но это действительно необязательно. Если вы пытаетесь реализовать интерфейс REST, Django REST Framework или Django Tastypie могут выполнить эту работу за несколько часов, потому что вся ваша бизнес-логика уже определена на общем языке, и все эти приложения извлекают из этого выгоду и прекрасно отображают эту логику.

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

Приложения — это просто хорошо упакованные функциональные возможности, у них есть модели, представления, URL-адреса и т.д., И это нормально, чтобы заставить их работать вместе. У вас могут быть взаимосвязи между приложениями (сообщение в блоге содержит много тегов). Конечно, если вы удалите тег application, возможно, ведение блога сейчас прекратится, поэтому подумайте об этом заранее (возможно, это тег, в котором много сообщений в блоге).

Если у вас есть еще какие-либо вопросы, задавайте мне в комментариях, и я постараюсь быть максимально ясным.

Комментарии:

1. Извините, я все еще в замешательстве с некоторыми вещами. Представьте, что на вашем веб-сайте есть концепции, которые используются многими функциями. Например, представьте понятия «Город» и «Страна», когда пользователь регистрируется, он указывает город / страну, в которой он живет, и в каждом сообщении в блоге он может указать город / страну, откуда он публикует. Используя ваш пример разделения приложений, куда бы пошли модели «Город» и «Страна»? Что касается пользователей, регистрации, ведения блога? Потому что эти две концепции будут использоваться в нескольких местах, и их можно использовать и в другом месте, и нам также нужно избегать циклических ссылок.

2. Кроме того, где будут такие операции, как «GetCitiesForCountry» или «GetTopPopulatedCityForCountry» или любая другая операция, которая может использоваться несколькими функциями (приложениями django)?

3. Кроме того, когда вы говорите, что было бы легко создать rest api, как бы вы этого добились? Допустим, у нас есть приложение, которое позволяет пользователям регистрироваться и имеет в моделях логику для регистрации нового пользователя. Для этого у нас было бы представление с формой, но мы также хотим представить эту логику через json api, но мы не хотим кодировать ее снова. Как бы вы использовали ту же бизнес-логику? И возможно ли создать это как другой проект? Потому что было бы хорошо, если бы мы внесли изменения в rest api, чтобы развертывать только rest api, а не все вместе.

4. Города и страны могут создавать собственные приложения, черт возьми, возможно, использовать другое автономное приложение, такое как GeoDjango, но это, возможно, излишество по сравнению с тем, чего вы пытаетесь достичь. GetCitiesForCountry и GetTopPopulatedCityForCountry можно было бы поместить в модель Country, чтобы вы могли вызывать country.get_cities() or country.get_top_cities() , country имея в качестве экземпляра Country Model.

5. Что касается REST Framework, то и Django REST Framework , и TastyPie предлагают свои собственные подклассы Django View, которые позаботятся об этом за вас, это действительно просто, но я не мог бы подробно рассказать об этом в комментарии. У вас могут быть приложения только с представлениями и без модели, так что вы можете отделить REST API вашего проекта от другого приложения, это также приложения без представлений, довольно распространенная практика.