1

I have a high level question about how to architect this app in django.

I have a few models that will undergo similar operation that will be performed on them by a view (like create, edit, save etc). You will also have some operations that are unique. Many of these operations are the same and I do not want to repeat the code. These models will have a few fields that are common among all of them, and they will also have field that are unique. What is the best way to design this?

The different models will be different apps. For example, the model can be school, church or restaurant. Therfore, you will have three apps. I suppose these models are subclassed from an abstract class. The views will also have some operations that are the same for all these three apps. Not sure how to write a common set of code, and have these three apps inherit something and then customize if needed. I just need some pointers/direction.

Edit: These models have a few common fields, but that is where the similarity ends. You could have models for schools , events or news articles (as you can see they can be completely different from a human point of view). I am going to add or remove these models as necessary, therefore, I must have separate apps. It almost seems like you need to create something that is common that you'd call in all these apps, but this common set exists for the model and views (almost need a framework that does all this I think).

Trewq
  • 3,187
  • 6
  • 32
  • 50

1 Answers1

4

This is more of a conceptual answer.

If the models are very similar, I think that they should belong in the same app. My reasoning is as follows. An app, again in my opinion, is a set of related data as well as business logic associated with that data and possibly even some logic as to how that data should be presented. So if the models are very common, it would seem that the data is somewhat related and therefore should in the same app.

However in my experience some apps can grow where I've had more then 20 models in a single app. That can get very difficult to manage in one models.py file, therefore I like to break models into a package. So then the structure of the app might look like:

project/
  manage.py
  project/
    __init__.py
    settings.py
    ...
  app/
    __init__.py
    ...
    models/
      __init__.py
      ...

The only thing is that if you do this, then you have to import all of the models in the model's __init__.py file and include them in __all__ variable. That way even though the models are structured as a package, in the rest of the code you can use them as a module.

The advantage of this approach is that you models are modular, which makes it much easier to maintain and it keeps relevant data in a single place.


As for business logic, I think inheritance should take care of many issues. You can always inherit from multiple classes. That allows you to make a set of base classes/models with a specific set of functionality in each and then just inherit from the appropriate base classes for your models. That will allow you to reuse as much of the code as possible.

Another approach is to use meta-classes. The idea is that you define a class which builds an instance of a different class. Example:

class FooMetaClass(type):
    def __new__(cls, name, bases, dict):
        # do some logic
        return super(FooMetaClass, cls).__new__(cls, name, bases, dict)

class FooClass(object):
    __metaclass__ = FooMetaClass
    ...

So the idea is that you can include some setting attributes in FooClass, and according to those attributes and possibly even their values, the meta-class can build out a customized instance of that class. At this point you can even generate dynamic things!

I found this approach useful a couple of times however in most cases I think that sub-classing should be more then enough.


For presentation, class based views are perfect. During this years DjangoCon, Kenneth Love gave a very good talk on class based views. Here you can see the slides: https://speakerdeck.com/u/kennethlove/p/views-can-be-classy and hopefully the video will be published soon. The big idea is that a class based view is identical to a function based view except the way it is structured.

I know in many of my projects, many of my views are pretty much identical. There is something going on in the beginning of the view, which is very similar across many views. Then there is some middle/meat section of the view, which is usually what is unique to each view. And then there is the end section of the view where I construct the context dictionary and return the response. So what I and many other developers end up doing is having a billion helper functions, which we call in other views to do certain repetitive tasks. This approach however makes code harder to read, sometimes introducing unnecessary abstractness since you have to pass many parameters to the helper functions, and finally just does not feel right.

This is where class based views come in. They do exact same thing as a function based view, except they break up the view into multiple function calls. So one function can be responsible for getting the object, another for constructing the context, and so on. Then when all of these functions are combined, then pretty much execute identical code to as what you might have in a function view. This however brings one major advantage. You can inherit views. So you can have one base class view for doing task a, and another for doing task b, hence you can make another view which inherits from both classes, hence doing both tasks. Additionally, once you inherit from some base view, you can overwrite whatever function base class defined, therefore giving even more flexibility.

That is very useful design pattern for doing common tasks for many similar views, yet minimizing the amount of code to write.


Hopefully this gives you some ideas as to how structure a project/app.

miki725
  • 27,207
  • 17
  • 105
  • 121
  • very much appreciate the time you took to write out the detailed reply. I have edited the question to describe why I'd need separate apps. I was thinking the same thing about the business logic and the view. If I just subclass the models from an abstract model, I will have what I need I think (??). Regarding the view, yes inheriting base views is the way to go - thanks. – Trewq Sep 14 '12 at 14:01
  • When I do different apps, then I usually create an app `data_structures` where I include all base classes, models, views, etc which I can reuse in other apps. An example of my base model would include the date created and date modified fields, or a note model which will have a notes field, etc. That will not really minimize the amount of code significantly but if the models are not very similar, that is probably the best you can do. – miki725 Sep 14 '12 at 18:51