django app organization - python

I have been reading some django tutorial and it seems like all the view functions have to go in a file called "views.py" and all the models go in "models.py". I fear that I might end up with a lot of view functions in my view.py file and the same is the case with models.py.
Is my understanding of django apps correct?
Django apps lets us separate common functionality into different apps and keep the file size of views and models to a minimum? For example: My project can contain an app for recipes (create, update, view, and search) and a friend app, the comments app, and so on.
Can I still move some of my view functions to a different file? So I only have the CRUD in one single file?

First, large files are pretty common in python. Python is not java, which has one class per file, rather one module per file.
Next, views, even as the standard used, is a python module. A module need not be a single file. It can be a directory containing many files, and __init__.py
And then, views.py is only a convention. You, the application programmer are referring to it, and django itself doesn't refer anywhere. So, you are free to put it in as many files and refer appropriate functions to be handed over, the request to, in the urls.py

They don't have to go in views.py. They have to be referenced there.
views.py can include other files. So, if you feel the need, you can create other files in one app that contain your view functions and just include them in views.py.
The same applies to models.py.
Django apps lets us separate common
functionality into different apps and
keep the file size of views and models
to a minimum? For example: My project
can contain an app for recipes
(create, update, view, and search) and
a friend app, the comments app, and so
on.
I don't know about the "to a minimum" part - some apps are just big in views, others big in models. You should strive to partition things well, but sometimes there is just a lot of code. But other than that, this is a fair summary of Django apps, yes.

I also very much dislike long files.
Of course what you read in the other answers is true, but I exploit some very nifty python equivalence:
views.py
and
views/__init__.py
are pretty much functionally equal - by that I mean that if the both contain def my_view() then
from views import my_view
will work the same in both cases!
From there it's easy to structure your long files into smaller ones, yet keeping the naming convention that every django developer is used to:
views/__init__.py
views/largemodel_view.py
then in __init__.py don't forget to import the views from largemodel_view.py.
With large applications I do the same with models though you must remember to set the Meta.app_name:
class MyModel(models.Model):
...
class Meta:
app_name = 'yourappname'
because django will not pick it up magically otherwise for the Admin (but it will still load it, thanks to Python!)
so my apps usually end up looking something like:
project/settings/__init__.py
/..othersettings..
/app_1/models/__init__.py
/...
/views/__init__.py
/...
/templates/
/static/
urls.py
/urls.py
etc.
though of course there's no limit (urls could be split too, etc.etc.)

Related

Is the naming convention in django mandatory?

In Django you name your files like models.py, views.py, urls.py and so on. I wonder, if this naming convention is mandatory for Django. Will Django's functionality break if you place your models in a file called foo.py? I mean, only the import-line should change, right? Or is there any magic with this named files done by the framework?
Of course, I won't give my files shitty names; but I am just curious.
views, urls can be configured.
url: You can defined your one urls by setting <project>.settings.ROOT_URLCONF, and include your apps' urls.
views: Import your views or use view names as you want.
But for models, there's assumption about the model module name in the django code and other third-party apps. (https://github.com/django/django/blob/stable/1.7.x/django/apps/config.py#L9)
The best is to create modules instead for a couple of reasons:
you'll keep it consistent with Django conventions making it easier for others to work on it
you can give more descriptive appropriate names to your files
you will avoid really long files
So you'd have:
- my_application
- urls
- sub_set_urls_1.py
- etc.
- models
__init__.py <= import your models in here
sub_set_models_1.py
etc.
- views
sub_set_views_1.py
etc.
It's a bit more involved for the models, you need to import the models in __init__.py. Another way is to have a models.py file and put your models somewhere else: Split models.py into several files

How do you actually use a reusable django app in a project?

This question has been troubling me for some days now and I've tried asking in many places for advice, but it seems that nobody can answer it clearly or even provide a reference to an answer.
I've also tried searching for tutorials, but I just cannot find any type of tutorial that explains how you would use a reusable third-party django app (most tutorials explain how to write them, none explain how to use them).
Also, I've taken a look here:
How to re-use a reusable app in Django - it doesn't explain how to actually use it IN a project itself
and here:
How to bind multiple reusable Django apps together? - the answer by aquaplanet kind of makes sense, but I thought I would ask this question to solve the mental block I am facing in trying to understand this.
In order to best explain this, let me do so by example (note, it is not something I am actually building).
I am creating a project that acts like Reddit. I will have users, links and voting/points. Based on this crude example, I will want to reuse 3 (arbitrary) third-party apps: user, voting/points and links.
I decide to use each of them as any other python package (meaning that they will be treated as a package and none of their code should be touched) [would this method actually work? Or do you have to be able to edit third-party apps to build a project??)
With these apps now within my project, I will use a main app to handle all the template stuff (meaning everything I see on the frontend will be in a single app).
I will then either use that same main app for custom logic (in views.py) or I will break up that logic among different apps (but will still use a single frontend-only app).
From the 3 paragraphs above, is this structure applicable (or can it work) ?
Now lets say that this structure is applicable and I am using a single main app for the frontend and custom logic.
What would I write in models.py? How would I integrate things from the 3 reusable apps into the main models.py file?
How would I reference the reusable apps in views.py? Lets take the example of contrib.auth
With this built-in app, for logging out I would write:
from django.contrib.auth import logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def user_logout(request):
logout(request)
return redirect('/home/')
Although the above code is simple, is that basically how things would be done with any reusable app?
My question is very long, but I think that this reusable app issue is something a lot of developers aren't quite clear about themselves and maybe this answer will help a lot of others who have heard about the promises of reusable apps, but fail to understand how to actually use them.
TL;DR:
Nope & it depends...
Some (Very) Common Reusable Apps
django.contrib.admin
django.contrib.auth
django.contrib.staticfiles
... those are all reusable Django apps, that happen to be shipped with Django (most of them were not, at some point in time)
Ok, some other reusable apps that don't ship with Django:
django-rest-framework
django-registration
South
Those are all truly reusable apps, and nothing less. There are very many more apps like that.
How do they do it?
To me your question looks more like "how do I build reusable apps", then "how to use them". Actually using them is very different from app to app, because they do very different things. There is only one rule: RTFM No way around that either.
Often, they rely on one or more of the following:
additional value(s) in settings.py
addition (usually one include statement) to urls.py
subclassing and/or mixins for Models, Forms, Fields, Views etc.
template tags and/or filters
management commands
...
Those are all powerful ways though which your app can provide functionality to other apps. There is no recipe (AFAIK) to make a reusable app, because there are so many different scenarios to consider. It all depends on what exactly your app should do.
Reusable apps provide functionalities
I'd argue that it's important to not think of reusable apps as "working together" with other app, but instead recognize that that they "provide functionality." The details of the functionality provided should dictate the way the target developer is supposed to use your library.
Not everything should be reusable
Obviously enough, even though many apps can "in principle" be reusable, it often makes little sense to do so, because it is way faster to clump things together (and make them just "work together").
I'm not sure why you think you need a main app for the "frontend" stuff. The point of a reusable app is that it takes care of everything, you just add (usually) a single URL to include the urls.py of the app, plus your own templates and styling as required.
And you certainly don't need to wrap the app's views in your own views, unless you specifically want to override some functionality.
I don't understand at all your question about models. There's no such thing as a "main" models file, and using a reusable app's models is just the same as using models from any of your own apps.
Normally you would not edit a third-party app, that would make it very hard to integrate updates. Just install the app in your virtualenv (you are using virtualenv, of course!) with pip, which will put it in the lib directory, and you can reference it just like any other app. Make sure you add it to INSTALLED_APPS.

django package organization

I plan to build my project in Django framework. However, I noticed that all Django packages have models.py file. Now, let say I have a set of general purpose functions that I share between several apps in the project and I plan to put these functions definitions in a separate package (or app for that matter?). So, should I create an app "general" and copy-paste these functions into the models.py file? Or can I just create a general.py file in the "general" app directory and leave models.py empty? What is the "Django" way to do that?
Thanks.
models.py file is used to define the structure of database. So you should leave it for defining your database entries. You can make an app named generals and put general.py in that app, and from there you can use it by calling it in any app.
I usually create a utils.py file under my main app that is created from the django-admin.py when starting the project.
I plan to put these functions definitions in a separate package (or app for that matter?)
Before you decide to make this an app (and if you do decide to make it an app), I recommend you take a look at James Bennet keynote on Developing reusable apps and hist post on laying out an application. From one of his slides:
Should this be its own application?
Is it orthogonal to whatever else I’m doing?
Will I need similar functionality on other sites?
Yes? Then I should break it out into a separate application.
If you're cramming too much functionality in one single general purpose app, it might be better to split your general purpose app into multiple reusable apps.
Going back to your original question, Django is expecting a models.py file in every app. So you must have the file even if it's empty.
Inside your models.py, you should only have the application’s model classes. So, you wouldn't be following a best practice if you put inside models.py some miscellaneous code you want to reuse.
From the laying out an application post I mentioned before:
At the application level, I usually drop in a few more files depending on exactly what the application is going to be using:
If the application defines any custom manipulators, I put them in a file called forms.py instead of in the views file.
If there are multiple custom managers in the app, I put them in a file called managers.py instead of the models file.
If I’m defining any custom context processors, I put them in a file called context_processors.py.
If I’m setting up any custom dispatcher signals, they go in a file called signals.py.
If the application is setting up any syndication feeds, the feed classes go in a file called feeds.py. Similarly, sitemap classes go in sitemaps.py.
Middleware classes go in a file called middleware.py.
Any miscellaneous code which doesn’t clearly go anywhere else goes in a file or module called utils.
All of this does not answer directly your original question:
can I just create a general.py file in the "general" app directory and leave models.py empty?
But I hope this gives you additional information to make a decision that better fits your project and requirements.

Django and MVC(MVT) layout

Im coming from using other MVC based frameworks, and going into Django, it seems a little awkward to what im used to. For example, in other MVC based frameworks. my layout might be like so:
root:
- config (houses the config files (like settings), url.conf, db connections, etc.)
- controllers (houses the main logic of each section of the site. The middle ground between views and models)
- models (handles all the data to be validated and anything that interacts with the database. declares the DB structure. each model a class, each attribute a db field. in django, a template?)
- views (the html displayed to the end user, put together by the controllers)
- tests (all the tests)
- plugins (3rd party apps you install into yours.)
- uploads (user uploaded files)
- public_html (the actual public facing files)
-\ css|js|img (the various static file types for page manipulation)
-\ index.html
That is what im used to, and it seems like django does things very differently. Where before if I had a poll app i would have:
controllers/PollController.py
models/Poll.py
views/poll/index.py
and that would create the poll table in the db. But in Django, how would I do this? Is this an acceptable layout? From what I have read, the above would be more like this:
root:
- project (this would be the main app, and what glues everything together)
--/ settings.py
--/ urls.py
--/ templates/
- apps
-/ Poll
--/ models.py (i would have no Poll.py model, so it would all go in here)
--/ urls.py (any url.conf specific to this model would go in here)
--/ templates/ (the various views for this app)
while this does makes sense in some ways, it just feel alien to me. Is there any benefit to this type of layout over a traditional mvc layout described in the first example? Is there another preferred layout beyond this? The purpose of this 'project' is that the core will be a basic framework for my own use and I have a few different 'apps' that i will create for each use of this framework. in the old version each application would just extend the main one by being a plugin in that directory.
As a background note, most of my experience is in php and the various frameworks from that worls (cakephp, yii, mostly), if that makes a difference. This will be my first main project in python/django. i just want to get it right.
The biggest benefit is that apps are modularized. You can remove your Poll application by deleting one directory instead of hunting through several directories deleting each piece. The flip side is if you found a Poll application somewhere that you wanted to use you can just drop in the one folder and you're good to go.
If you approach the idea of a site being a conglomeration of several individual and mostly distinct "apps" with some glue to hold them together then this organization makes much more sense.
Is there any benefit to this type of layout over a traditional mvc layout described in the first example?
Yes.
What you appear to be calling "Traditional MVC" is just another framework. It's not magically better or more right. It's just different.
Is there another preferred layout beyond this?
There are probably hundreds of ways to do this. Django chose one that fits nicely with Python and web applications.
i just want to get it right.
Then do this.
Discard your preconceptions left over from other things you've done.
Start fresh and empty with Django like a complete beginner.
After you've learned your 6th framework, you can then (and only then) compare and contrast the six frameworks you've learned. Until you've learned six, each one has to be taken as new, complete, different and unique.
Don't compare and contrast yet.
Just take Django as Django and do things the Django way.
(For more metaphorical advice, read about the music of Django Reinhardt; he had a unique view and a unique approach to the guitar.)
Notes
root # doesn't mean anything
config -- Doesn't exist.
controllers -- Doesn't exist.
models -- A Python module with the class definitions for the persistent objects. Maps to RDBMS schema. Can have model-specific tests.
views -- A Python module with view functions that respond to requests and create responses.
test -- A Python module with View-specific and template-specific tests.
plugins -- Doesn't exist.
uploads -- Runtime, not development of the application.
public_html -- Does not exist.
css|js|img -- Static "Media" files. Runtime, not development.
index.html -- Does not exist.
Stuff you omitted
templates -- your HTML template pages, used by the view functions.
admin -- admin bindings for the default admin site. Relies on modules and forms.
forms -- form definitions; these are classes that produce forms used for input validation.
urls -- mappings from URL paths to view functions.
settings -- module with default database configuration, middleware, etc.

About 20 models in 1 django app

I have started work on a local app for myself that runs through the browser. Having recently gone through the django tutorial I'm thinking that it might be better to use django rather than just plain python.
There's one problem: I have at least 20 models and each will have many functions. Quite simply it's going to create one huge models file and probably huge views too. How do I split them up?
The models are all related so I can't simply make them into separate apps can I?
This is a pretty common need... I can't imagine wading through a models.py file that's 10,000 lines long :-)
You can split up the models.py file (and views.py too) into a pacakge. In this case, your project tree will look like:
/my_proj
/myapp
/models
__init__.py
person.py
The __init__.py file makes the folder into a package. The only gotcha is to be sure to define an inner Meta class for your models that indicate the app_label for the model, otherwise Django will have trouble building your schema:
class Person(models.Model):
name = models.CharField(max_length=128)
class Meta:
app_label = 'myapp'
Once that's done, import the model in your __init__.py file so that Django and sync db will find it:
from person import Person
This way you can still do from myapp.models import Person
"I have at least 20 models" -- this is probably more than one Django "app" and is more like a Django "project" with several small "apps"
I like to partition things around topics or subject areas that have a few (1 to 5) models. This becomes a Django "app" -- and is the useful unit of reusability.
The overall "project" is a collection of apps that presents the integrated thing built up of separate pieces.
This also helps for project management since each "app" can become a sprint with a release at th end.
The models are all related so I cant's
simply make them into separate apps
can I?
You can separate them into separate apps. To use a model in one app from another app you just import it in the same way you would import django.contrib apps.
Having 20 models in one app might be a sign that you should break it up in smaller ones.
The purpose of a Django app is to have a small single-purpose piece of code, that fits nicelly together.
So, if you had a e-commerce site, you might have a shopping_cart app, a billing app, and so on.
Keep in mind that there is really no problem in apps depending on each other (although it's always better if they can be decoupled), but you should not have an app doing two very distinct things.
The article Django tips: laying out an application might help you. As always, take everything you read with a grain of salt (including this answer).
You can break up the models over multiple files. This goes for views as well.
You can split them into separate files and simply have imports at the top of your main models.py field.
Whether you'd really want to is another question.

Categories