I'm using django as my framework for some web application.
I implemented a modelview of my own because I have a few querysets and seriazliers in the same view.
For this use, I needed to implement all of the CRUD functions myself:
class Models1AndModel2View(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
model1 = Model1.object.all()
model1_serializer_class = Model1Seriazlizer
model2 = Model2.object.all()
model2_serializer_class = Model2Seriazlizer
def refresh_querysets(func):
def inner(self, *args, **kwargs):
value = func(self, *args, **kwargs)
self.model1 = Model1.object.all()
self.model2 = Model2.object.all()
return value
return inner
@refresh_querysets
def list(self, request, *args, **kwargs):
...
@refresh_querysets
def retrieve(self, pk, request, *args, **kwargs):
...
@refresh_querysets
def update(self, pk, request, *args, **kwargs):
...
@refresh_querysets
def delete(self, pk, request, *args, **kwargs):
...
@refresh_querysets
def create(self, request, *args, **kwargs):
...
Notice that I'm calling the decorator's function before the objects refresh. I noticed that every attribute set after the function calls is not actually set.
For example - some test of mine:
I changed the order on the inner function of the decorator, and it worked as expected.
def refresh_querysets(func):
def inner(self, *args, **kwargs):
self.model1 = Model1.object.all()
self.model2 = Model2.object.all()
return func(self, *args, **kwargs)
return inner
I believe your issue is because the view is temporary.
You save self.model1
on the view which is destroyed and recreated per request.
There is no point updating the self
if the object will be destroyed.
Also, you should remember that model1
as set in the class variable is initialized on class creation only, and not on instance creation, meaning it will always contain the original data from when you imported that respective module.
There are 3 options to solve it:
Change the order of the function decorator as you've done, setting self.model1
before running the function, or pass it as a parameter.
Change model1
on __init__
, and so the changes will apply on instance creation.
While frowned upon, the class attribute model1
is right now equivalent to a "class global" (and has almost all of a global downsides). You can simply change it like so:
self.__class__.model1 = Model1.object.all()
Keep in mind I do not believe this class attribute should even exist. Should it be immutable, setting it on the instance creation makes more sense.
Either case, I'm not sure if you wish to dump the entire object / DB at every request. I do not know if django smartly caches object.all()
(and updates the cache upon modification), but if it doesn't it'll be a major slowdown.