2

Just working through some CBV work, and was wondering if this is bad style. Normally you have a class in your views.py and a URL in urls.py for that view. Something like:

views.py

from django.views.generic.list import ListView
from project.models import Contact

class ContactList(ListView):
  model = Contact

urls.py

from django.views.generic.list import ListView   
from project.views import ContactList

urlpatterns = [
    url(r'contacts/$', ContactList.as_view()),
]

and then a template to show the data.

But, what about just skipping the view code entirely and doing it all like this within the urls.py file:

from django.views.generic.list import ListView
from project.models import Contact

urlpatterns = [
    url(r'contacts/$', ListView.as_view(model=Contact)),
]

Is that bad style to group it all into the urls.py file? I mean, it gets rid of excess code inside views.py so isn't that good? Or is this a reduction at the expense of clarity?

jpic
  • 32,891
  • 5
  • 112
  • 113
Garfonzo
  • 3,876
  • 6
  • 43
  • 78

3 Answers3

5

It is much more better to keep view logic out of URLConfs. At a glance url(r'contacts/$', ListView.as_view(model=Contact)) might seem okay, but actually it violates the Django design philosophies:

  • Loose coupling between urls, views, models has been replaced with tight one, so now you can't reuse your view.
  • Flexibility of URLs is destroyed. Inheritance, the main advantage of CBV is impossible using them in URLs.
  • Many other things, for example what if you want to add authentication? Authorization? You will need to wrap all these in decorators and your URLs will quickly become messy.

So:

  • Views modules should contain view logic.
  • URL modules should contain URL logic.
pythad
  • 4,241
  • 2
  • 19
  • 41
  • I'm certainly not convinced, you can live with `url(r'contacts/$', ListView.as_view(model=Contact))` until you need to reuse that view - but obviously you have no reason to do so at this stage. – jpic Nov 27 '15 at 09:31
  • Moving the definition of the view from urls.py to views.py does NOT achieve loose coupling in anyway !! It's just moving code around !!! oh god – jpic Nov 27 '15 at 09:32
  • What if you want to add authentication ? You can still decorate the view in urls.py. What if you need something really more complex ? then just declare the view in views.py, be **pragmatic**, care about what you need **now**, not about what **you might need tomorrow**. – jpic Nov 27 '15 at 09:34
  • @jpic, do you understand the difference between word `should` and `must`? – pythad Nov 27 '15 at 10:33
  • I see, but that still makes your statement about loose coupling invalid. – jpic Nov 27 '15 at 10:55
  • @jpic, I never wrote that it's invalid, of course it's valid, the code will work. I said that it violates some philosophies. I read this in `Two scopes of Django` and think that they are right. – pythad Nov 27 '15 at 11:19
  • If the components call each other, they are coupled, it doesn't matter if it's coupled through an import of views or not. – jpic Nov 27 '15 at 14:41
2

The answer is: it depends.

If you're writing a really small app that, you know, won't get bigger, then it doesn't matter, unless you can't resist code smells, you can actually write your whole app in just one file, check answers to this SO question for example How do I write a single-file Django application?

P.S: This problem is universal and is in no way Django specific.

Community
  • 1
  • 1
HassenPy
  • 2,083
  • 1
  • 16
  • 31
  • What do you mean it "kills the MVT" ? When the code grows, move it away, you talking about MVC to support poor arguments, how does that make the code harder to read since you're going to read urls.py anyway to find out which view was used for a specific url (unless you're using django-debug-toolbar of course, then you just now). Put you on the watch list ? oh god ... – jpic Nov 27 '15 at 09:48
  • 1
    having to jump from views.py to urls.py to just tell what a view does is a code smell, and yes what you said is right, i just drove away from the subject by mentioning MVC, i probably had other thought in mind i didn't express well. thanks – HassenPy Nov 27 '15 at 11:56
0

Well, "reducing excess code in views.py" is certainly not a reason. If you're going to instanciate generic views with a couple of simple arguments, you can keep it in urls.py, as long as it works for you. When it doesn't work anymore, maybe move it to views.py or make views a module and move it to views/someview.py, it doesn't matter.

jpic
  • 32,891
  • 5
  • 112
  • 113