25

This is really just a "best practices" question...

I find that When developing an app, I often end up with a lot of views.

Is it common practice to break these views up into several view files? In other words... instead of just having views.py, is it common to have views_1.py, views_2.py, views_3.py (but named more appropriately, perhaps by category)?

Brant
  • 5,721
  • 4
  • 36
  • 39

3 Answers3

38

Splitting views.py

Most of your code probably expects your views to be accessible as myapp.views.viewname. One way I've seen people break up their views but keep this python name is to create a views/ directory. views/__init__.py will have:

from .foo_views import *
from .bar_views import *
from .baz_views import *

Then, in views/foo_views.py, put:

def foo_detail(request, ...):
    # your code here

def foo_list(request, ...):
    # your code here

def your_other_view(...):
    # ...

etc. So you move everything from views.py into files in this directory, make __init__.py, delete views.py, and you're done.

Then, when you import myapp.views, myapp.views.foo_detail will refer to the function that you defined in views/foo_views.py.

Splitting other modules

This strategy should also work fine for admin.py, etc. But if you want to split up models.py like this, you will need to add app_label = 'your_app_name' to the class Meta: of all of your models. For example, unicorn_app/models/unicorns.py could have an entry like this:

class Unicorn(models.Model):
    description = models.CharField(max_length=80)

    class Meta:
        app_label = 'unicorn_app'

(Otherwise, Django imagines that the Unicorn model is part of a Django app named "models", which messes up the admin site. Current through 1.6 - the upcoming 1.7 release will remove this requirement.)

rescdsk
  • 8,739
  • 4
  • 36
  • 32
  • I like this approach. The only problem is that now I need to put full paths when I import other things from the app. For example, before I could do "from models import *". Now I need to do "from project.app.models import *". Is there any way to fix that? – Brant Apr 21 '10 at 16:08
  • 3
    You can do relative imports. I've never tried them and they seem a bit tricky, but here's a relevant SO question: http://stackoverflow.com/questions/72852/how-to-do-relative-imports-in-python – rescdsk Apr 23 '10 at 20:03
  • 1
    Addendum- the directories with `__init__.py` files are called "packages". – Matt Luongo May 02 '12 at 14:45
  • I realize this is a kinda old answer. But another question. """So you move everything from views.py into files in this directory, make __init__.py, delete views.py, and you're done. Then, when you import myapp.views, myapp.views.foo_detail will refer to the function that you defined in views/foo_views.py.""" Does this create any kind of performance hit by importing then importing, etc ? – Josh Brown Feb 27 '14 at 05:20
  • Python modules are cached, so while it might be a tiny bit slower each time your app is restarted, it should be just as fast after that. But any difference should be quite small compared to other design decisions that you make when building a web app. – rescdsk Feb 27 '14 at 17:12
  • Awesome. Tidy, elegant ... I don't know why it's not "the recommended way of doing it", in the tutorial etc! – GreenAsJade Nov 29 '14 at 01:23
4

As a general guideline, think about readability and maintainability: the default "views.py" is just a suggestion made by initial scaffolding - you do not have to stick to it.

Usually, files with thousands of lines of code are difficult to maintain, for this I usually try to decompose bigger modules into smaller ones.
On the other hand, the division should make sense - splitting related functions into several files, with lots of imports may make maintenance even more difficult.

Finally, you can also think about completely other ways to simplify your application.
Do you see duplicated code? Maybe some functionality could be moved in a completely different application? And so on.

rob
  • 36,896
  • 2
  • 55
  • 65
3

Another option would be to move some of the functionality into one or more apps. This would allow you to move also forms and templates and keeping things structurized. You don't necessarily need to move the models which saves you from model and data migration.

For example you could have the following structure:

main_app/
  |_models.py
  |_views.py
  |_forms.py
  |_urls.py
  |_templates/

sub_app_1/
  |_views.py
  |_forms.py
  |_urls.py
  |_templates/

sub_app_2/
  |_views.py
  |_forms.py
  |_urls.py
  |_templates/
Nathan
  • 2,955
  • 1
  • 19
  • 17
  • I recognize what the other guy is saying, but I like this more. It makes complete thoughts between subject matter in your app. +1 Thanks. – arcee123 Aug 18 '18 at 17:04