Hacker News new | past | comments | ask | show | jobs | submit login

The projects/app relationship never 'clicked' with me. I also have a dislike for the awkward 'polls' example in the django tutorial.

That said, I like Django. Of course, I liked Rails better, but maybe that's because it was my 'first' and I never used any of the big php frameworks for a long period of time.

I quit wasting my time with Flask for projects a while ago. It's a really great project and suited for smaller things, but you just end up re-implenting django. I'd rather someone made those decision for me.




> The projects/app relationship never 'clicked' with me.

This is an area that I think is poorly documented (both in the otherwise-great official docs and in the broader community). My advice for beginners is to just create an app called `core` and put everything there, until you have a reason to do something else. (I'd also propose putting your DJANGO_SETTINGS_MODULE aka "project name" as "django_settings" and only put your Django settings in there, but that's a little more esoteric and I'd not recommend that to a newbie in order to minimize confusion.)

In general, I think you should take the "monolith first" strategy (e.g. https://martinfowler.com/bliki/MonolithFirst.html) and just use a single app, unless you're writing something that is obviously going to be reused elsewhere.

The alternative is to attempt to define service boundaries before you know what your app's structure looks like; you'll inevitably get it wrong. And migrating models between apps is incredibly painful if you have foreign keys spanning apps.

I've also found a couple bugs in Django's migration machinery that only affect multi-app foreign key relationships; I've never seen a single-app migration bug. So there's a real cost to going down the multi-app path, which you need to balance against any benefits (I've seen none).

(Credentials/disclaimer; startup using DRF in prod for 3.5 years, mature domain model with ~50 model classes, feeling the pain of incorrectly choosing 5 apps in the initial setup instead of just using one. I'm sure there's a good argument for apps when you get to a larger scale and are sharing components/functionality between teams.)


>> I quit wasting my time with Flask for projects a while ago. It's a really great project and suited for smaller things, but you just end up re-implenting django

This is spot on .... Flask is great, but it seems that to get anything substantial done with Flask you must first reimplement big chunks of Djangoesque functionality in it - why not just jump straight to Django?


Yeah that or just plug in 5-6 extensions and you end up with the same. Found myself doing flask-sqlalchemy, flask-migrate, etc. after a while.


We split into multiple apps within one project/site for separation of concerns instead of reusability. We have ~370 apps and nest them quite heavily, probably ~30 at the top level. This works well for us and we've managed to scale nicely to 15 people working on the codebase quite nicely.


What do you mean by nesting apps? Like group them into domain folders and have multiple apps within a domain folder?


I assume Dan really means a nested directory structure, like so:

django_project/top_level_app/second_level_app/

in top_level_app you then could do

from second_level_app.models import model1

or from a different top level app:

from other_top_level_app.second_level_app.mixins import a_mixin


Yep, exactly this. For example: project/orders/orders_shipping/orders_ups

Unfortunately app names have a global namespace within Django's model registry, so we often have to prefix nested apps.

The place where this really works nicely is user facing features and internal editing interfaces, or in features where we have N of a feature that are all similar. For the former, we might have an app such as "blog", and then a nested app within that called "blog_editor". This way we can separate blog models, business logic and user-facing behaviour, from CRUD interfaces designed for internal users. In the latter, if we have 3 shipping providers, we might have an app "shipping" with the core shipping models, with nested apps for "ups", "royal_mail", "dpd", etc, each of which might have the necessary models needed to manage uploading to their APIs, business logic, etc. There may be a common-ish interface exposed by these apps.

This structure is probably the thing I like most about Django over, say, Rails. It's not necessary for all Django projects, but I think it's pretty nice.


Within a single app, could this not be done mith multiple model files, and multiple services files.

I usually organize my apps by having a services layer between models and views, such that the view functions have little to no knowledge about the underlying models.

This, in place of nested apps, I have "upsmodels.py" and "upsservice.py" and the view functions handles routing logic.


That would indeed work, however given that one app can have ~20 nested apps at the first level, this might become tricky to manage. There's a lot to be said to having a directory with ~5 files in it that is all you need to keep in your head for a feature.


Two Scoops books about Django have awesome tips and tricks about many topucs and architecture is one of them.

Even if the latest version is for 1.11, the concepts are relevant.


Mozilla has some large, public Django projects on Github that are worth taking a look at to see how they're splitting up apps.

https://github.com/mozilla/addons-server


I feel the same way. Does any one have a good overview on how the community actually separates functionality into “apps”?

I have been looking at a rails like framework in python called Masonite. Does anyone in the python/Django community think this will gain traction?


The separate apps thing is overblown (although that sentiment seems to be shared in these comments). If you're making a monolith web app, you can be safe just chucking it into one django app. If you're concerned about code organization, you can do that in one app with either sub apps or just turning files into packages later. I think this is a more productive strategy for django beginners.

If you've identified some clean, generic problem where you want to reuse the code or open source it, make it a separate app. If you have a web site with areas that barely interact with each other, make it into separate apps (a chef's website where the recipes are separate from the cooking classes calendar). If you know what you're doing and feel like separate apps will help with organization, then split them up as well. Otherwise, one is fine.


> Does any one have a good overview on how the community actually separates functionality into “apps”?

For the most part there isn't any need to, with the exception of things explicitly meant to be shared. So if you are a large company and want a bunch of custom auth logic or something to be shared among many different teams running their own Django service, then you might want to build that as an app. Or else if you were building something as an open source project you might want to do the same.

In terms of separating apps by functionality, I think the main reason many people do it is because they are under the mistaken impression that putting things into different apps will make them magically re-usable. That's not to say you shouldn't do it, only that I think most people do it for the wrong reasons.

In general I would say don't bother splitting up your project into different apps by functionality until you have too many models to comfortably fit into one file. That might not be until 20KLOC. For apps that are less than 10KLOC, I think in most cases the overhead probably outweighs the benefits.

There isn't really any hard rule one how to do this, but you might do something like:

- Account management app for creating and deleting users, getting user profiles, password resets, etc.

- Apps for integrations with third-party APIs, e.g. Duns or Mailgun.

- Apps for different front doors, e.g. if you make a Facebook chat bot that's powered by the same tech that powers your normal website.

And then after that you can possibly split up your business logic of your core website into different logical components, but I would do that last. By the time you get there you should start to have a feel for how to do this.

The one place I use it for our own startup is that we recently built a couple different front doors for our site, and each one accepts data in a slightly different format and has different authentication requirements. I put each of these in their own apps, but everything else is just in one main app.


> until you have too many models to comfortably fit into one file. That might not be until 20KLOC.

Even for larger apps in my django project, I convert my models into a package and split all my models into individual files (same with views and serializers for DRF). This keeps my models easier to manage.


Apps can be a good way to generalize a set of classes for reuse in other projects. For instance we put auth into an app so if we fire up other projects we don’t have to rewrite auth.


Thanks for the thoughtful response. Do you find yourself repeating code, or struggling to decide where code should live and where it should be imported?


I had this problem for the first couple years, but not anymore. What I did:

- I split the core app up into different views and services based on the functionality. For FWD:Everyone this is basically: account_management, admin_apis, content_discovery, organizations, upload_thread, read_thread, comments, and user.

I have a folder for all my views and a folder for all my services, and for each view there is one (or occasionally two) service files.

So e.g. in the views folder there is a file called account_management_views, and then in the services folder there is a file called account_management_service.

For utilities that get re-used across the entire app I have two additional things in the services folder, one is called util.py and the other is io_util.py.

Util is for things like sanitizing XSS that don't require any database access, and io_util is for things like get_user_from_username, get_user_from_email_address, etc.

Then you can import any models into io_util.py, but never into util.py. And you can import anything from util.py into io_util.py, but never the other way around. Then you can import anything from either util or io_util into any service method and shouldn't have any issues. (Although I always just import util or io_util, and then call the methods like util.sanitize_xss.)

Once I structured the services and utilities that way I never had issues again with circular imports or figuring out where to put stuff. Importing with Python is kind of difficult and janky in general, but so far this pattern seems to be working pretty well for both our startup and also for the consulting projects I've done.

Basically for logic that's mostly specific to a single view, put it in the services file for that view. Public functions in that folder can still be re-used in other services, but if they're fairly generic and they're re-used in more than one or two places then consider moving them into util or io_util so as to avoid circular import issues.


There's no hard rules about app separation. Here are some from my experience:

- You may have stuff that may be re-used for multiple projects. For example the departments of your organization and their attributes; these should be extracted to apps so they can be easily used for other projects. Of course this would make sense if you are a software house or an organization that need multiple apps (i.e a bank) not if you are working for a single application.

- Django recommends using a custom user model. I put that in a separate app along with any related classes like user preferences etc. See also my previous bullet.

- Non related models. If you add a model that doesn't have any relation to the rest of your models then maybe you should move it to a different app? For example in one of my applications I have a NewsItem model that is just a bunch of notes that the admins can add and will be visible to the homepage; there's no need to put it in with the rest of the app (of course this also obeys the 1st bullet)

- Beyond that, usually you'll understand when you have to separate your apps. You don't need to force it, I know of huge apps with a models or views py with thousands of lines (of course in such cases even if you think that these should belong to the same app nothing's stopping you from making them a package instead of a module). However you'll usually come to a point where you think that for your reasons you need to separate


I don't use multiple apps anymore and instead treat the project as the app, so my directory structure looks something like this ('project' can change to something specific to what you're working on):

* manage.py

* project/settings.py

* project/urls.py

* project/models/ (each model gets it's own file here)

* project/views/ (same for views)

...and so on. And in `INSTALLED_APPS` I just add 'project'.

Makes it so I don't waste a bunch of time trying to figure out which app to put a model in, etc.


That looks like rails. What made you settle on this given that Django promotes a different structure? I am curious as I like this approach as well, but would be nervous about making life harder by not following the framework and community path.


Been building Django apps for almost 10 years and after seeing the amount of wasted time going into organizing things into apps, I settled on this technique.

It doesn’t really swim against the current as long as you import models into the __init__.py file in their package.


We do this too on some projects, it's painless. As far as I know Django doesn't really have an opinion on this, you have a lot of freedom in how you organize your project.


I've never gone so far as each model getting its own file. Interesting idea.


They're just modules by another name.

The way I think about design is usually centered around the data model, so if some subject has a number of ORM models and is pretty self contained it makes sense to put them in their own app, together with related urls and views and stuff.

They still live in the same repository and aren't meant to be re-used, just split into logical parts to make the code base easier to think about. Modules, in other words.


As a Django enthusiast and python programmer, I often want less magic from Django, not more. This makes pyramid or flask seem tempting to me. If I wanted Rails that badly, I would simply port my code to Ruby.


Django is supposed to be the “Rails” of Python, allowing programmers who want a Rails-like experience to continue using Python instead of switching languages completely.

If you don’t want “magic” then your solution is right - just use Flask.


The thing with the "magic" of django is that you don't need to use it! It's up to you whether you want to use the magic or not! The magic is powerful. The thing that turns users away is learning the magic.


Django's supposedly independent components were built with the context of the rest of Django in mind and have all kinds of default behaviors based on that. Surely they may work without the rest, but it isn't nearly as smooth as working with independent libraries that were designed with a much more limited scope.


> Django is supposed to be the “Rails” of Python, allowing programmers who want a Rails-like experience to continue using Python instead of switching languages completely.

A small nitpick: While Django may indeed fill that role, it's actually older than Rails, so wasn't "supposed" to do that. Both projects have been created independently of each other.


I think pyramid or flask has more traction nowdays.


For small projects, I usually have two apps, the frontend and backend apps.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: