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.