Django: "projects" vs "apps"
Asked Answered
E

6

222

I have a fairly complex "product" I'm getting ready to build using Django. I'm going to avoid using the terms "project" and "application" in this context, because I'm not clear on their specific meaning in Django.

Projects can have many apps. Apps can be shared among many projects. Fine.

I'm not reinventing the blog or forum - I don't see any portion of my product being reusable in any context. Intuitively, I would call this one "application." Do I then do all my work in a single "app" folder?

If so... in terms of Django's project.app namespace, my inclination is to use myproduct.myproduct, but of course this isn't allowed (but the application I'm building is my project, and my project is an application!). I'm therefore lead to believe that perhaps I'm supposed to approach Django by building one app per "significant" model, but I don't know where to draw the boundaries in my schema to separate it into apps - I have a lot of models with relatively complex relationships.

I'm hoping there's a common solution to this...

Ensample answered 2/2, 2011 at 19:41 Comment(1)
The docs explain the difference between "application" and "project" here: docs.djangoproject.com/en/dev/ref/applications/…Lizzettelizzie
D
59

What is to stop you using myproduct.myproduct? What you need to achieve that roughly consists of doing this:

django-admin.py startproject myproduct
cd myproduct
mkdir myproduct
touch myproduct/__init__.py
touch myproduct/models.py
touch myproduct/views.py

and so on. Would it help if I said views.py doesn't have to be called views.py? Provided you can name, on the python path, a function (usually package.package.views.function_name) it will get handled. Simple as that. All this "project"/"app" stuff is just python packages.

Now, how are you supposed to do it? Or rather, how might I do it? Well, if you create a significant piece of reusable functionality, like say a markup editor, that's when you create a "top level app" which might contain widgets.py, fields.py, context_processors.py etc - all things you might want to import.

Similarly, if you can create something like a blog in a format that is pretty generic across installs, you can wrap it up in an app, with its own template, static content folder etc, and configure an instance of a django project to use that app's content.

There are no hard and fast rules saying you must do this, but it is one of the goals of the framework. The fact that everything, templates included, allows you to include from some common base means your blog should fit snugly into any other setup, simply by looking after its own part.

However, to address your actual concern, yes, nothing says you can't work with the top level project folder. That's what apps do and you can do it if you really want to. I tend not to, however, for several reasons:

  • Django's default setup doesn't do it.
  • Often, I want to create a main app, so I create one, usually called website. However, at a later date I might want to develop original functionality just for this site. With a view to making it removable (whether or not I ever do) I tend to then create a separate directory. This also means I can drop said functionality just by unlinking that package from the config and removing the folder, rather than a complex delete the right urls from a global urls.py folder.
  • Very often, even when I want to make something independent, it needs somewhere to live whilst I look after it / make it independent. Basically the above case, but for stuff I do intend to make generic.
  • My top level folder often contains a few other things, including but not limited to wsgi scripts, sql scripts etc.
  • django's management extensions rely on subdirectories. So it makes sense to name packages appropriately.

In short, the reason there is a convention is the same as any other convention - it helps when it comes to others working with your project. If I see fields.py I immediately expect code in it to subclass django's field, whereas if I see inputtypes.py I might not be so clear on what that means without looking at it.

Die answered 2/2, 2011 at 19:58 Comment(3)
+1... "What is to stop you using myproduct.myproduct?" - Django's "startapp" command actually stops you, I assume, as a convention. I like conventions, especially in the context of a team effort, but I prefer to understand the logic behind them :)Ensample
@Ensample ah, does it? I haven't used it since the first time I used it because I have my own command for creating a project that first creates models then auto-generates CRUD stuff for these models. Still, yes conventions are good. I follow django conventions if only because largely speaking they make sense.Die
I'll add that using the same name for a project and an app within it also causes problems with manage.py, causing it to be unable to import your project settings correctly. This happened to me, and I solved it by refactoring the app to the effect of myproduct_app.Baber
C
104

Once you graduate from using startproject and startapp, there's nothing to stop you from combining a "project" and "app" in the same Python package. A project is really nothing more than a settings module, and an app is really nothing more than a models module—everything else is optional.

For small sites, it's entirely reasonable to have something like:

site/
    models.py
    settings.py
    tests.py
    urls.py
    views.py
Cephalad answered 15/3, 2013 at 14:58 Comment(4)
+1 Summary: project has settings.py, app has models.py. They are the same level structure. I used to think project is one level higher than app, guess I were wrongLoot
@Cephalad , what should be included in settings (as app) in order to allow 'python manage.py makemigrations' or 'python manage.py migrate' to see the 'models.py' file in 'my product' directory ?Receptionist
@Receptionist I realize I'm super late at answering this but I'm in similar situation myself and I've been looking at a lot of answers. To answer your question, all you need to do is include your project in the INSTALLED_APPS list. Here is an example: https://mcmap.net/q/120498/-how-to-structure-template-libraries-in-a-django-project-closedOutflank
@KarthicRaghupathi, Thanks.. :) nice to see comments being answered after four years.. cheersReceptionist
W
72

Try to answer question: "What does my application do?". If you cannot answer in a single sentence, then maybe you can split it into several apps with cleaner logic.

I read this thought somewhere soon after I've started to work with django and I find that I ask this question of myself quite often and it helps me.

Your apps don't have to be reusable, they can depend on each other, but they should do one thing.

Widmer answered 2/2, 2011 at 20:1 Comment(1)
I'm still struggling a bit when it comes to laying out my own app. I feel like my main application is a bit heavy, but at the same time, I wouldn't be able to refactor it into anything close to resembling something loosely coupled. I'm leaning toward thinking that it wouldn't really be an improvement to have my main major entities separated, if they still depend heavily on one another, and there's no need to reuse or generalize on the horizon. I'm leaning toward "don't prematurely refactor" as an interpretation of "don't prematurely optimize"Remount
D
59

What is to stop you using myproduct.myproduct? What you need to achieve that roughly consists of doing this:

django-admin.py startproject myproduct
cd myproduct
mkdir myproduct
touch myproduct/__init__.py
touch myproduct/models.py
touch myproduct/views.py

and so on. Would it help if I said views.py doesn't have to be called views.py? Provided you can name, on the python path, a function (usually package.package.views.function_name) it will get handled. Simple as that. All this "project"/"app" stuff is just python packages.

Now, how are you supposed to do it? Or rather, how might I do it? Well, if you create a significant piece of reusable functionality, like say a markup editor, that's when you create a "top level app" which might contain widgets.py, fields.py, context_processors.py etc - all things you might want to import.

Similarly, if you can create something like a blog in a format that is pretty generic across installs, you can wrap it up in an app, with its own template, static content folder etc, and configure an instance of a django project to use that app's content.

There are no hard and fast rules saying you must do this, but it is one of the goals of the framework. The fact that everything, templates included, allows you to include from some common base means your blog should fit snugly into any other setup, simply by looking after its own part.

However, to address your actual concern, yes, nothing says you can't work with the top level project folder. That's what apps do and you can do it if you really want to. I tend not to, however, for several reasons:

  • Django's default setup doesn't do it.
  • Often, I want to create a main app, so I create one, usually called website. However, at a later date I might want to develop original functionality just for this site. With a view to making it removable (whether or not I ever do) I tend to then create a separate directory. This also means I can drop said functionality just by unlinking that package from the config and removing the folder, rather than a complex delete the right urls from a global urls.py folder.
  • Very often, even when I want to make something independent, it needs somewhere to live whilst I look after it / make it independent. Basically the above case, but for stuff I do intend to make generic.
  • My top level folder often contains a few other things, including but not limited to wsgi scripts, sql scripts etc.
  • django's management extensions rely on subdirectories. So it makes sense to name packages appropriately.

In short, the reason there is a convention is the same as any other convention - it helps when it comes to others working with your project. If I see fields.py I immediately expect code in it to subclass django's field, whereas if I see inputtypes.py I might not be so clear on what that means without looking at it.

Die answered 2/2, 2011 at 19:58 Comment(3)
+1... "What is to stop you using myproduct.myproduct?" - Django's "startapp" command actually stops you, I assume, as a convention. I like conventions, especially in the context of a team effort, but I prefer to understand the logic behind them :)Ensample
@Ensample ah, does it? I haven't used it since the first time I used it because I have my own command for creating a project that first creates models then auto-generates CRUD stuff for these models. Still, yes conventions are good. I follow django conventions if only because largely speaking they make sense.Die
I'll add that using the same name for a project and an app within it also causes problems with manage.py, causing it to be unable to import your project settings correctly. This happened to me, and I solved it by refactoring the app to the effect of myproduct_app.Baber
K
16

I've found the following blog posts very useful about django applications and projects:

In principle, you have a lot of freedom with django for organizing the source code of your product.

Keshiakesia answered 2/2, 2011 at 19:54 Comment(0)
R
8

If so... in terms of Django's project.app namespace, my inclination is to usemyproduct.myproduct, but of course this isn't allowed

There is nothing like not allowed. Its your project, no one is restricting you. It is advisable to keep a reasonable name.

I don't see any portion of my product being reusable in any context. Intuitively, I would call this one "application." Do I then do all my work in a single "app" folder?

In a general django project there are many apps (contrib apps) which are used really in every project.

Let us say that your project does only one task and has only a single app (I name it main as thethe project revolves around it and is hardly pluggable). This project too still uses some other apps generally.

Now if you say that your project is using just the one app (INSTALLED_APPS='myproduct') so what is use of project defining the project as project.app, I think you should consider some points:

  • There are many other things that the code other than the app in a project handles (base static files, base templates, settings....i.e. provides the base).
  • In the general project.app approach django automatically defines sql schema from models.
  • Your project would be much easier to be built with the conventional approach.
  • You may define some different names for urls, views and other files as you wish, but I don't see the need.
  • You might need to add some applications in future which would be real easy with the conventional django projects which otherwise it may become equally or more difficult and tedious to do.

As far as most of the work being done in the app is concerned, I think that is the case with most of django projects.

Retrospect answered 2/2, 2011 at 21:22 Comment(1)
+1, esp for the main convention - that makes a lot of sense to me for an original project like this. I do plan on adding "reusable" apps later, but that's way outside my focus right now.Ensample
S
2

Here Django creators points out that difference themselves. I think that thinking about Apps as they have to be reusable in other projects is good. Also a good way of thinking about Apps in Django provide modern web applications.

Imagine that you are creating big dynamic web app basing on JavaScript.

You can create then in django App named e.g "FrontEnd" <-- in thins app you will display content.

Then you create some backend Apps. E.g App named "Comments" that will store user comments. And "Comments" App will not display anything itself. It will be just API for AJAX requests of your dynamic JS website.

In this way you can always reuse your "Comments" app. You can make it open source without opening source of whole project. And you keep clean logic of your project.

Simulation answered 5/12, 2017 at 10:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.