I've begun diving into Django again and I'm having trouble finding the parallel to some common concepts from my life in C#. While using .NET MVC I very often find myself creating a base controller which will provide a base action implementation to take care of the type of stuff I want to do on every request, like retrieving user information, getting localization values.
Where I'm finding myself confused is how to do this in Django. I am getting more familiar with the MVT concept but I can't seem to find how to solve this scenario. I've looked at class based views and the generic views yet they didn't seem to work how I expected. What am I missing? How can i create default logic that each view will be instructed to run but not have to write it in each view method?
If it is truly common for your whole site you use middleware. If it is only common for some views, the way to go in my opinion is to create decorators for those views. I never use class-based views because I tend to keep views simple and put more logic into models, so I have no need for classes there.
Related
I'd like to ask you if you can clear something up to me. I'm designing a web app powered by Django and I'm also learning about OOP as I go.
From what understand main purpose of class-based views is to keep my code DRY. To avoid any repetitive or redundant code.
I've tried to implement class-based views however at the end I always ended up tossing everything into function-based view 'coz all the views are fairly unique.
When I looked over the views I asked myself: "Does your code repeat anywhere ?" Answer was no.
The question is: Despite using classed-based views being considered to be the best coding practice it's not always possible. Am I right ?
Class-based views are not inherently better than function-based views. In many cases it's a matter of preference. However, as you get further along in Django you will see that many of the features you'll be using are used in the same view (loading a template, for example) and you may find it easier to modify or extend an existing default CBV than writing a brand-new function every time.
Your question will probably be closed as opinion-based, but I recommend taking what you have over to the Code Review Stack Exchange and getting some feedback there.
https://simpleisbetterthancomplex.com/article/2017/03/21/class-based-views-vs-function-based-views.html
I have subclassed Django's generic views for my project. I use them extensively to create basic CRUD views on our front-end site. Some models have just a create view, some have a read and update, etc.
This works well but I still write a line of code for each URL. ie:
url(r'^referrer/create/$',ReferrerCreateView.as_view(), name='referrer_create'),
url(r'^referrer/$',ReferrerListView.as_view(), name='referrer_list'),
url(r'^referrer/(?P<pk>\d+)/update/$',ReferrerUpdateView.as_view(),
name='referrer_update'),
I then do this for every model and the views that model has. This doesn't seem to be a very DRY approach to me. Is there a good approach to automating these urls for any generic view that has been created for a model?
The solution is to create a method that will return a list of url() calls given a set of views. Something like
views = {
'base_name': 'referrer',
'create_view': ReferrerCreateView,
'list_view': ReferrerListView,
'update_view': ReferrerUpdateView,
}
def generate_urls(views):
return [
url(r'^%s/create/$' % views['base_name'], views['create_view'].as_view(), '%s_create' % views['base_name'],
# and so on
]
Then you just need to do
urlpatterns = patterns('', *generate_urls(views))
For every set of views you have.
That being said I believe you shouldn't do this. This solution (or any different implementations) is over complicated and will add an extra layer you'll need to go through if things go wrong.
There's nothing wrong of having some boilerplate code, especially configuration code, because it makes your life much easier to debug in the future.
I have the same very concern and I shared it here before
One answer was the use of django rest framework as it implements such url patterns on its own!?! I didn't experience this solution yet.
My workaround is to have a dedicated file for crud operations for every model.
By that solution I decreased the matching time , and grouped related model pattern in one file.
BUT I understand that wont fully solve your question
This issue has been tormenting me for a while already. I've read about this topic but nothing seems to clear my thoughts. I understand that they call the views templates, and the models models as well, what I don't really get is where the controllers are. What django calls views seem to me more like actions/methods/functions of a controller than a controller itself, but anywhere I read, I find that supposed view-controller equivalency.
I've worked with MVC frameworks before (ASP.NET MVC3, Ruby on Rails, PHP Laravel Framework), and they all define the controllers as the same thing: a bunch of functions related to a specific topic of the site, namely user accounts or something like that. The best equivalency that I find between this description and django features are the apps, but of course I'm wrong due to the huge amount of people and documentation going the other way.
Could anybody help me with this? Does my mindset make any sense? Am I missing something essential here and then I can't get these concepts right?
It's a mistake to think of design patterns like MVC as unbreakable rules. They really aren't: there are all sorts of ways of implementing them, which comply with the description to a greater or lesser extent.
This is especially the case in Python, where one of the guiding principles is "practicality beats purity" - in other words, do what works.
In any case, Django makes no claim to be an MVC framework. On the contrary, the documentation describes it as MTV: model, template, view. After all, outside the world of design patterns everyone calls "an HTML file with syntax for variables and flow control" a template, not a view.
(That FAQ entry also offers a possible answer to your question: the controller is the framework itself. But it goes on to emphasise that it's a mistake to try to shoehorn into these definitions.)
The views.py defines the view functions for your app and your app groups related functions together.
However what I believe you're missing here is the urls.py.
The urls file is the first part of the controller.
The URL patterns inside urls.py dictates what you're allowed to pass in to the view function or view class (depending on what approach you took, either with function based views or class based views) and then routes it to the proper view function.
So there's tight a coupling between the views.py and the urls.py, that makes up for the entire Controller part of MVC.
Comparing it to Rails, would be that the urls.py is a routes.rb and the actual controller class is the views.py function/cbv.
The mismatch of terminology is unfortunate but more or less doing the same thing.
You can read the Django FAQ. It explains the how MVC is implemented in django. Regarding controller Django has an answer as:
.
Where does the “controller” fit in, then? In Django’s case, it’s probably the framework itself: the machinery that sends a request to the appropriate view, according to the Django URL configuration.
Could anybody help me with this? Does my mindset make any sense? Am I missing something essential here and then I can't get these concepts right?
The only well-defined parts of MVC where nearly everyone had some sort of consensus is the M; the V and C means completely different things in different web frameworks, to the point where MVC framework really only means as not having all your code in one spaghetti (ala typical classical PHP code). You just had to accept that MVC isn't a really well defined term.
Django is not strictly speaking MVC.
I found this discussion very enlightening:
Django is not MVC
Realy guys:
DJANGO is MVC!
But word View use for Controller.
And Django is Full MVC, but
Model - Model
View - Template
Comtroller - View
I'm working on an e-commerce framework for Django. The chief design goal is to provide the bare minimum functionality in terms of models and view, instead allowing the users of the library to extend or replace the components with their own.
The reasoning for this is that trying to develop a one-size-fits-all solution to e-commerce leads to overcomplicated code which is often far from optimal.
One approach to tackling this seems to be using inversion-of-control, either through Django's settings file or import hacks, but I've come up against a bit of a problem due to how Django registers its models.
The e-commerce framework provides a bunch of abstract models, as well as concrete versions in {app_label}/models.py. Views make use of Django's get_model(app_label,model) function to return the model class without having to hard-code the reference.
This approach has some problems:
Users have to mimic the structure of the framework's apps, ie the app_label and effectively replace our version of the app with their own
Because of the way the admin site works by looking for admin.py in each installed app, they have to mimic or explicitly import the framework's admin classes in order to use them. But by importing them, the register method gets called so they have to be unregistered if a user wants to customise them.
The user has to be extremely careful about how they import concrete models from the core framework. This is because Django's base model metaclass automatically registers a model with the app cache as soon as the class definition is read (ie upon __new__), and the first model registered with a specific label is the one you're stuck with. So you have to define all your override models BEFORE you import any of the core models. This means you end up with messy situations of having a bunch of imports at the bottom of your modules rather than the top.
My thinking is to go further down the inversion-of-control rabbit hole:
All references to core components (models, views, admin, etc) replaced with calls to an IoC container
For all the core (e-commerce framework) models, replace the use of Django's base model metaclass with one that doesn't automatically register the models, then have the container explicitly register them on startup.
My question:
Is there a better way to solve this problem? The goal is to make it easy to customise the framework and override functionality without having to learn lots of annoying tricks. The key seems to be with models and the admin site.
I appreciate that using an IoC container isn't a common pattern in the Django world, so I want to avoid it if possible, but it is seeming like the right solution.
Did you look at the code from other projects with a similar approach?
Not sure if this way covers your needs, but imo the code of django-shop is worth to look at.
This framework provides the basic logic, allowing you to provide custom logic where needed.
customize via models
eg see the productmodel.py
#==============================================================================
# Extensibility
#==============================================================================
PRODUCT_MODEL = getattr(settings, 'SHOP_PRODUCT_MODEL',
'shop.models.defaults.product.Product')
Product = load_class(PRODUCT_MODEL, 'SHOP_PRODUCT_MODEL')
customize via logic/urls
eg see the shop's simplevariation-plugin
It extends the cart-logic, so it hooks in via urlpattern:
(r'^shop/cart/', include(simplevariations_urls)),
(r'^shop/', include(shop_urls)),
and extends the views:
...
from shop.views.cart import CartDetails
class SimplevariationCartDetails(CartDetails):
"""Cart view that answers GET and POSTS request."""
...
The framework provides several points to hook-in, the simplevariation-plugin mentionned above additionally provides a cart-modifier:
SHOP_CART_MODIFIERS = [
...
'shop_simplevariations.cart_modifier.ProductOptionsModifier',
...
]
I worry that this explanation is not very understandable, it is difficult to briefly summarize this concept. But take a look at the django-shop project and some of its extensions: ecosystem
I accept that the question is a bit subjective, and that it does not pin point at certain technical doubt/query, but i wanted to know.
I am a newbie in django, after 3-4 months of doing apps in django i am trying to dig-down-deep.
I am currently reading a book by James Brennet where he shows how to use generic views, but when i head to https://docs.djangoproject.com/en/dev/topics/ i see generic views are depricated.
From the "best design perspective" point of view, how is using generic views rated?
Is it considered a good practice to use generic views?
If yes why is then django depricating it?
If no, what else is recommended?
Thanks!
The old generic views are deprecated because they've been replaced with 'Class-based generic views':
https://docs.djangoproject.com/en/dev/topics/class-based-views/
If you have a lot of view which repeatedly express the same pattern, for example a set of CReate/Update/Delete (CRUD) views for several models... where most of the view code is the same but just some specifics change, eg the model class and final redirect url... this is where generic views make sense.
The goal is to be DRY (Don't Repeat Yourself) ...ie write the code in one place and re-use, catch and fix bugs in one place etc.