What really is the true meaning of django project and individual apps in it?
I mean - AFAIK you cannot create a project and live entirely in that project you created, you have to create an app in that project to be able to actually do something in django. Please correct me if I'm wrong.
Now what should really be the structure of a django project? I'm writing an e-shop. Let's say my project is named foo:
/foo
/foo
/settings.py
/templates
/urls.py
/wsgi.py
/shop
/__init__.py
/admin.py
/models.py
/tests.py
/views.py
and do everything entirely in /foo/shop/, but I edit urls.py inside /foo/foo/ etc.
I was following the Django Book, but I've begun to gain that strange feeling that /foo/foo/ is just for a main folder "stitching the thing together" but individual stuff should be done only in /foo/shop/, but not limited to. Preferably in /foo/web/, /foo/products/, /foo/forum/, /foo/controlpanel/, /foo/shop/, /foo/helpdesk/, /foo/backoffice/ etc.
Is that correct? Should I put everything products-related in /foo/products/, that including storage management, shipping, dealers, prices etc., then put management of those products (from the employee side) to /foo/backoffice/, which will serve as some sort of "django.contrib.admin" for this? Is that correct? Then if I want to host multiple instances of this (with completely separate databases and stuff) for multiple customers, should i only create a barebone project, that will put these things together, to configure the settings and then just move individual components in some sort of central repository and call them back in the project via INSTALLED_APPS? Because that would be cool as hell! I mean - making all the changes globally, not touching users data and configuration, unless necessary (adding columns in models and such). Is this how django is really supposed to be used? Or am I completely off the track and do things ENTIRELY wrong and this paragraph just doesn't make any django-sense?
I'm relatively new to this. I've been using PHP before and even though Django was a pain-in-the-ass to get basic grip of, I don't regret that and plan to deprecate and make offline any PHP project I created to date and replace them all with django. Well - where it makes sense and is not a single-purpose site. Not only because Django is awesome and versatile, but i cas I can scale it easily as well…
So… How should I really design Django projects, apps, and how to use them in production, providing them to multiple customers?
Thank you!
I mean - AFAIK you cannot create a project and live entirely in that project you created, you have to create an app in that project to be able to actually do something in django. Please correct me if I'm wrong.
You can do plenty of things on just a project, but you need an app for models to be auto discovered.
For example, I have a project with just this in urls.py:
class Homepage(generic.TemplateView):
template_name = 'homepage.html'
def get_context_data(self):
context = cache.get('homepage')
if not context:
management.call_command('reset_cache')
context = cache.get('homepage')
return context
urlpatterns = patterns("",
url(r"^$", Homepage.as_view(), name="home"),
)
You guessed it, it's a really basic website.
and do everything entirely in /foo/shop/, but I edit urls.py inside /foo/foo/ etc.
I was following the Django Book, but I've begun to gain that strange
feeling that /foo/foo/ is just for a main folder "stitching the thing
together" but individual stuff should be done only in /foo/shop/, but
not limited to. Preferably in /foo/web/, /foo/products/, /foo/forum/,
/foo/controlpanel/, /foo/shop/, /foo/helpdesk/, /foo/backoffice/ etc.
Well, you should define /foo/shop/urls.py, and import it from /foo/foo/urls.py ie.:
urlpatterns = patterns("",
url(r"^shop/", include("shop.urls")),
)
The point is to make your apps more convenient to reuse in other django projects.
Is that correct? Should I put everything products-related in
/foo/products/, that including storage management, shipping, dealers,
prices etc., then put management of those products (from the employee
side) to /foo/backoffice/, which will serve as some sort of
"django.contrib.admin" for this? Is that correct?
You should take a look at open source projects and see how they divided that.
According to the directory tree that you represented, you seem to have understood the point, but your statement seems fuzzy so I'll attempt to clarify it.
Apps are generally oriented around models. So if I make a product app it will probably contain:
Product model,
Product list, edit, create, delete and detail view
urls for the views,
Product admin,
tests for Product and views,
other things which are used by other django apps like product/admin.py would be used by django.contrib.admin, but also external apps like django-autocomplete-light would use product/autcomplete_light_registry.py and django-rules-light would use product/rules_light_registry
Then if I want to host multiple instances of this (with completely
separate databases and stuff) for multiple customers, should i only
create a barebone project, that will put these things together, to
configure the settings and then just move individual components in
some sort of central repository and call them back in the project via
INSTALLED_APPS?
There are many ways to do SaaS with django. But I agree that the easiest and most convenient is to maintain generic apps and build a project per customer that reuses (and eventually override parts of) these apps.
Related
I'm currently writing django project and got confused when it came to separation into apps. Project consists of posts and categories which are kept in one app, also there is a 'main' app which handles user profile view, login, logout and registration. Now I'm trying to implement user-to-user messages and I'm wondering if it should be kept as separate app.
If Message model is kept in application 'messages' how do I realize show_messages view?
1) It seems that it should be stored in 'main' app since it's linked by my_profile view. It would just get all Message instances form 'messages' app and render template extending profile.html or including from 'messages' app a partial template responsible only for messages listing. But why would I then need separate application just to hold one model there with some helper functions?
2) Secondly I wonder about placing show_messages view in 'messages' app but then I would need to use template which extends template from other application which again seems to be violation of self-containment rule. Also all "accounts/" urls are currently kept in main.urls so I feel wrong about adding "accounts/profile/messages" rule to messages.url.
3) Finally I think about moving Message model with all helpers and templates to 'main' app since messages are designed to work with User models and views therefore forcing additional separation seems useless.
Thanks for reading my thoughts, I'll appreciate all clues and explanations.
When I first started working with Django, I found the answers on this SO question to be particularly helpful, regarding app/project layout: Projects vs Apps
Many of the answers are useful, but this one is particularly pithy:
Try to answer question: "What does my application do?". If you cannot answer in single sentence, then maybe you can split it to several apps with cleaner logic?
I've read this thought somewhere soon after I've stared to work with django and I find that I ask this question my self 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.
Interdependence of apps isn't always problematic. For example, in a lot of my projects I have a separate app that is used solely for creating dynamic menus. In order to work properly, I need to import the specific models of that site into that app -- so I couldn't just drop it into another site, unaltered, and expected it to work. Nonetheless, the other 90% of the code in that app is completely reusable, and it's easier for me to move the relevant code to a new project if its already spun out into a separate app -- even though that app only holds a templatetag and a template.
Ultimately, a django site would technically run just fine with ALL models/views/etc in one big, unwieldy app. But by breaking your project down into "this app performs this specific function" you're probably going make managing your code a lot easier for yourself.
Regarding the 'url' point in 2, there's no reason not to subspace URLs. You are already doing this in a django project already -- mostly likely your main urls.py has an include() to another app, such as your main.urls. There's no reason your main.urls can't also have an include() to your messages app.
I am trying to figure out general guidelines for arranging views/templates in a django project with multiple apps so that the apps remain fairly re-usable.
For specific example:
I have a django project with three main apps:
- accounts: That manages user account related stuff
- reports: That generates reports
- courses: That manages course contents
I also have a \templates directory in the project, and have three directories under it corresponding to each of the three apps. This breakdown works well for me on pages that deal with individual app elements.
However, there are views and pages where I need to show information collected from all three apps. For example, I might want to show an overview page with the User payment status (accounts), his past reports(reports) and his current course(course).
I understand that apps must be kept as independent as possible. What are the guidelines for place views/templates that do not clearly belong to one app but import from different apps? Should I create a project-specific app just to hold these views/templates?
It depends on how re-usable you need to make these shared templates. I often just put these sorts of templates into a "shared" directory. Sometimes I'll have a "shared" that applies to the entire project, and sometimes I'll have one that is shared within an app. It just depends on what works best for you.
I have just learnt about Django apps. I want to know that within one site, if I make different apps. like, users, profiles, polls, blogs,comments, jobs , applications then how can I manage them to make them intereactive? And is it how the concept of app should be? I want to have things loosely coupled that's why asking? Rails work on the way of REST, so do Django support that also with the use of apps? May be my questions seems a bit ambiguous because I am new to django and some of my concepts are still messed up.
Please tell what ever you know.
The general idea is that apps should be as loosely coupled as possible. The goal is to have completely self-contained functionality. Now, of course, that's not always possible and many times it even makes sense to bring in functionality from another app. To do that, you simply import whatever you need. For example, if your "blogs" app needed to work with your Comment model in your "comments" app you'd simply add the following to the top of the python file you're working in:
from comments.models import Comment
You can then use Comment as if it were defined right in the same file.
As far as REST goes, Django's views are much more fluid. You can name your view whatever you like; you need only hook it up to the right urlpattern in urls.py. Django views can return any content type, you just prepare the response and tell it what mimetype to serve it as (the default is HTML).
Often I create a static html prototype/skeleton for back-end developers I work with. This helps to find mistakes in the UI/IA and costly re-writes before the site is implemented.
I would like to take this a step further and create these prototypes/skeletons in Django. By a prototype/skeleton I mean linked static pages that can be easily hooked up to back-end later.
I would like to get some suggestions/ideas how I should set up my templates/links so they are easy to work with later during the implementation stage.
Short list of requirements that come to my mind:
Organization of templates while the entire project will consist of multiple apps
Clean URL dispatcher and link creation
Ability to display logged-in/ logged-out states
I guess in a more traditional approach, the UI designers and back-end developers work on two ends of the development spectrum and hopefully converge somewhere in the middle in a gracious manner. If you'd be willing to get your hands dirty with writing a few lines of code, you could lay out the whole application architecture for the developers because you have the upper hand—your immediately concerned with the users, the data they consume and the interactions they need to perform. That would take out much of the guesswork for the developers, now with only having to fill in the holes, connect the dots or what have you.
The first thing you should do is get together and set some common grounds. Typically, that includes performing modularization at the very beginning. Take all the major features and break them into several Django apps that are going to wrap template, view and model triads relevant to a certain feature the application provides. The more the better holds true here, so don't worry if you end up with a lot of applications, because you never want to have a single application providing too many features/hosting too many components. Commonly you start with apps such as registration, authentication, profiles (user) and work you way outwards. As an example, you could cram the three into a single application, but you end up with a lot of templates, a lot of views, two or three models perhaps, but the tests are really going to be a real choking point. So, break everything into these app buckets until you feel that every part of the system naturally falls into place on a conceptual level. If your ever find yourself thinking where something should be placed, or your looking at a module that's several pages long and feel tempted to break the module (models.py, views.py, test.py) into a package with many intra-package modules, you should probably refactor the architecture immediately. Always remember that your efforts here are to strike simplicity with your architecture.
Once that's done, you've really done half of the work. Great thing about Django is that you have loose coupling between URLs and views. The views themselves provide the application behavior and streamline the presentation. If you can properly pave out the main URLs and stub out the views to just churn out static templates, you've just done some fine work.
This is how it's accomplished. You can abstract URLs and the views they're mapped to by naming your patterns, such as authentication:login, authentication:logout, registration:register, registration:confirm, registration:activate, etc. This is how you tie your internals to all the behaviors that are provided and these shouldn't be subject to change. You can then always change the URL pattern for authentication:login, change the view that pattern maps to, but your referencing it by an internal name, so you can, say, swap out the views that just churned out static templates with a full blown view without having to do any additional modifications to your code.
So here's how it works in real life:
Brainstorm, decide on the apps and the features they'll provide and review your decisions.
Start of with a core application that's going to host some project specific features, such as base templates and the root / view.
Create a /core/templates/core/base.html that's going to load all the common CSS/JS files that are going to be used site-wide, that'll define the header, contents and footer sections (template blocks) and that's going to use context variables for page metadata, such as title, description, keywords and robots. Your typical "One Template To Rule Them All", the bits that are going to be present in structure/presentation for all of your pages.
Create a simple /core/temaplates/core/welcome.html, that extends the core template and prints "Hello world!" in the content area.
Add the following to /core/urls.py:
from django.conf.urls.defaults import *
from django.views.generic import TemplateView
urlpatterns = patterns('',
# Welcome
url(
r'^$', TemplateView.as_view(template_name='core/welcome.html'),
name='welcome'
),
)
Hook it up in the main /urls.py:
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(ur'^', include('core.urls', namespace='core')),
url(ur'^admin/doc/', include('django.contrib.admindocs.urls')),
url(ur'^admin/', include(admin.site.urls)),
)
Hit http://localhost:8080/, see the "Hello World!", revel in the warm fuzzy feeling.
Repeat the same for the rest of the apps: create the app, create the patterns, name them, map them to a static template, hook it to a namespace in the main urlconf.
You can push the views even further to production readiness for the developers. It might depend on the devs and their style guidelines, but I like to keep my /urls.py clean of everything else but patterns, names and view mappings. Your /core/urls.py could look like:
from django.conf.urls.defaults import *
from core import views
urlpatterns = patterns('',
# Welcome
url(
r'^$', views.Welcome.as_view(),
name='welcome'
),
)
Edit /core/views.py with the following:
from django.core.views.generic import TemplateView
class WelcomeView(TemplateView):
template_name='core/welcome.html'
extra_context={
'page_title': 'Welcome!',
'page_keywords': 'relevant,page,keywords',
'page_description': 'Something equally relevant',
}
def get_context_data(self, **kwargs):
context = super(WelcomeView, self).get_context_data(**kwargs)
context.update(self.extra_context)
return context
And that's one sturdy stubbed-out view, packed with page metadata! Definitely the stuff that'll earn you a beer from the devs. Keep on doing this for all of the views to pump out static templates. When someone approaches to finalizing the views, they'd just have to inherit from a different view class, add the missing features, extend the context, modify the template and voila--it's ready for production.
There's not a lot of upfront learning you'd have to do to make this possible, but it really takes out a lot of the guesswork for devs, which are naturally more concerned with building the rest of the application. It's also simple enough to get really good at, I would guess no one would mind letting you do all of this work. As added beef, you'll probably not be kept in the dark as to how the template context gets populated in the views, so even you can start rolling out more complex views, or at least be able to read them.
When I start an application, I usually make a prototype version as well in Django. I just use direct_to_template generic views, which can later be replaced with the views that the developers create. Since you have multiple apps, you can store app specific templates in a folder in your templates folder that has the same name as the app.
The end result is that you have all the screens displaying at the right urls and can link between them. All developers need to do is replace each url with the custom view they create. Makes it easy.
You may have to do a bit of code if you want the logged in/out status to display, but it is definitely doable.
While working on my Django-based projects I'm always trying to follow Django's approach to reusable apps - I'm trying to decouple my applications from each other and especially trying to avoid cross references but sometimes it does not seem to be possible.
Let's consider a simple example with 2 applications: articles and users. Articles application defines article model, articles list view and single article view, users application defines user model and user profile view. Article is referencing user from the author field, so articles application is obviously dependent on users application which is fine.
But when it comes to user profile, I want to display latest articles authored by the user (and may be latest articles viewed by the user) on that page but that makes users application aware of articles application which is what I'm trying to avoid.
I can obviously try to push all such references to the template level but it still does not solve the issue completely and at the same time may be very inefficient in terms of database queries sometimes.
What do you guys do in such cases?
If you are really set on not having any conversation between the 'user' app and the 'article' app, then you need a third app to act as interface. That would know about users and articles and define all the coupling between them. Your article view would be in there, since it has to get the user data, and your user profile view would be in there, because it needs to say "Fred wrote 5 articles".
Whether this level of decoupling is worth it, I don't know. Sometimes programming for re-usability gets in the way of making the thing usable in the first place.
The standard (or preferred) way of keeping coupled apps decoupled is to add a conditional coupling - like in some apps that try to import django-notification and only if they find it, they report events to it.
Still, if you have two apps that talks to each other by design, then I don't see any point in decoupling them - there are plenty of examples in Django world of apps that just require other apps. Note that I'm talking here about writing real-world software, not about some academic delibrations :-)
It seems that in this case, the dependency of users on articles is in a method, not a field. (Whether it's a model method, a model class method, or a manager method is immaterial). If that's so, you can do a lazy import of articles inside the method. By the time this import is performed, users.models will be fully loaded, so even if this is a circular import, it will not cause problems. The "import users" statement in articles will not have to re-load users and will have the full users namespace available.