Reputation: 563
I have a web application with many models and many class based views. The most part of code looks like this
from typing import TypeVar, Type
M = TypeVar('M', bound='Model')
TypeModel = Type[M]
# ---------- models
class Model:
@classmethod
def factory(cls: TypeModel) -> M:
return cls()
class ModelOne(Model):
def one(self):
return
class ModelTwo(Model):
def two(self):
return
# ---------- views
class BaseView:
model: TypeModel
@property
def obj(self) -> M:
return self.model.factory()
def logic(self):
raise NotImplementedError
class One(BaseView):
model = ModelOne
def logic(self):
self.obj. # how can i get suggest of methods of ModelOne here?
...
class Two(BaseView):
model = ModelTwo
def logic(self):
self.obj. # how can i get suggest of methods of ModelTwo here?
...
I want to have a property obj
which is instance of specified model in view. How can I achieve this?
Thank you
Upvotes: 2
Views: 2238
Reputation: 63978
You need to make your BaseView
class generic with respect to M
. So, you should do something like this:
from typing import TypeVar, Type, Generic
M = TypeVar('M', bound='Model')
# Models
class Model:
@classmethod
def factory(cls: Type[M]) -> M:
return cls()
class ModelOne(Model):
def one(self):
return
class ModelTwo(Model):
def two(self):
return
# Views
# A BaseView is now a generic type and will use M as a placeholder.
class BaseView(Generic[M]):
model: Type[M]
@property
def obj(self) -> M:
return self.model.factory()
def logic(self):
raise NotImplementedError
# The subclasses now specify what kind of model the BaseView should be
# working against when they subclass it.
class One(BaseView[ModelOne]):
model = ModelOne
def logic(self):
self.obj.one()
class Two(BaseView[ModelTwo]):
model = ModelTwo
def logic(self):
self.obj.two()
One note: I got rid of your TypeModel
type alias. This is partly stylistic and partly pragmatic.
Stylistically, when I look at a type signature, I want to be able to immediately determine whether or not it's using generics/typevars or not. Using type aliases tends to obscure that/I don't really like using context-sensitive types.
Pragmatically, both PyCharm's type checker and mypy tend to struggle a little when you make excessive use of type aliases containing typevars.
Upvotes: 3