I am trying to work out how to inherit variables from a parent class.
I have two classes (simplified but same principle):
class Database(object):
def __init__(self, post, *args, **kwargs):
self.post = post
self.report()
def report(self):
#... obtain variables from post ...
self.database_id = self.post['id']
#... save data to database
class PDF(Database):
def __init__(self, post, *args, **kwargs):
Database.__init__(self, post, *args, **kwargs)
#... if i try to access self.database_id now, it returns an error ...
print(self.database_id)
instantiating script:
Database(request.POST)
PDF(request.POST)
I have tried just instantiating CreatePDF, as i thought the Database.__init__(self, post, *args, **kwargs) line would the Database class, but this does not work either.
I am trying to find the most pythonic way to do inherit. I can obviously obtain self.database_id from the post dict passed to PDF(), however I do not see the point in doing this twice, if I can use inheritance.
Thanks
Use:
class PDF(Database):
def __init__(self, post, *args, **kwargs):
# Stuff
super().__init__(post, *args, **kwargs)
The correct approach to instantiated an inherited class is to call super().init(args), which in this case calls Database.init because of method resolution order.
See http://amyboyle.ninja/Python-Inheritance
Related
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:
list all the models - 2 models instances
delete one of them
list them again - still 2 models instances (in model1 + model2)
if you query the model1 and model2 you can see that one of the instances is deleted as expected, but the model1 was not refreshed.
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.
I want to get <Model> value from a URL, and use it as an __init__ parameter in my class.
urls.py
url(r'^(?P<Model>\w+)/foo/$', views.foo.as_view(), name='foo_class'),
views.py
class foo(CreateView):
def __init__(self, **kwargs):
text = kwargs['Model'] # This is not working
text = kwargs.get('Model') # Neither this
Bar(text)
...
Clearly, I'm missing something, or my understanding of URL <> class view is wrong.
You should override dispatch method for such use cases.
class Foo(CreateView):
def dispatch(self, request, *args, **kwargs):
# do something extra here ...
return super(Foo, self).dispatch(request, *args, **kwargs)
For your specific scenario, however, you can directly access self.kwargs as generic views automatically assign them as an instance variable on the view instance.
I wrote pretty simple code, but I want to know is it proper way to resolve problem:
from selenium import webdriver
class MyClass(webdriver.PhantomJS):
def __init__(self, *args, **kwargs):
phantomjs_path = 'node_modules/.bin/phantomjs'
self.driver = webdriver.PhantomJS(phantomjs_path)
super().__init__(phantomjs_path, *args, **kwargs)
I created class, which inherit from selenium.webdriver.PhantomJS - of course I execute super(). Additionaly I create object self.driver.
Can/Should I combine last two lines in one?
You'd not use the second-last line at all. You are creating another instance inside your subclass there. self.driver is basically the same thing as self now, only without your extra methods.
Omit it altogether:
class MyClass(webdriver.PhantomJS):
def __init__(self, *args, **kwargs):
phantomjs_path = 'node_modules/.bin/phantomjs'
super().__init__(phantomjs_path, *args, **kwargs)
In your method, self is the instance already.
This is my code:
class SocialNodeSubscription(model.Model):
def __init__(self, *args, **kwargs):
permissions=["post","read","reply","admin"]
for p in permissions:
self.__dict__["can_"+p]=model.BooleanProperty(default=True)
I need to dynamically define fields in my model but this doesn't seem to work because dict is not the right place where to put my fields.
For who don't know about ndb, this is how it would look like going the easier way.
class SocialNodeSubscription(model.Model):
def __init__(self, *args, **kwargs):
self.can_write=model.BooleanProperty(default=True)
self.can_read=model.BooleanProperty(default=True)
...
Edit:
Now my code looks like this:
def __init__(self, *args, **kwargs):
permissions=["post","read","reply","admin"]
for p in permissions:
self._properties["can_"+p]=model.BooleanProperty(default=True)
self._fix_up_properties()
But still i get this error.
File "C:\Program Files
(x86)\Google\google_appengine\google\appengine\ext\ndb\model.py", line
972, in _store_value
entity._values[self._name] = value TypeError: 'NoneType' object does not support item assignment
What does it mean?
It's _properties,
just have a look at its metaclass MetaModel and class method _fix_up_properties.
Definition of _properties:
# Class variables updated by _fix_up_properties()
_properties = None
Method:
#classmethod
def _fix_up_properties(cls):
"""Fix up the properties by calling their _fix_up() method.
Note: This is called by MetaModel, but may also be called manually
after dynamically updating a model class.
"""
Use an expando model for a model with dynamic properties.
This question is about Python inheritance but is explained with a Django example, this should't hurt though.
I have this Django model, with Page and RichText models as well:
class Gallery(Page, RichText):
def save(self, *args, **kwargs):
# lot of code to unzip, check and create image instances.
return "something"
I'm only interested in using the save method in another class.
A solution could be:
class MyGallery(models.Model):
def save(self, *args, **kwargs):
# here goes the code duplicated from Gallery, the same.
return "something"
I'd like to avoid the code duplication and also I'm not interested in inheriting members from Page and RichText (so I don't want to do class MyGallery(Gallery):. If it would be legal I'd write something like this:
class MyGallery(models.Model):
# custom fields specific for MyGallery
# name = models.CharField(max_length=50)
# etc
def save(self, *args, **kwargs):
return Gallery.save(self, *args, **kwargs)
But it won't work because the save() in Gallery expects an instance of Gallery, not MyGallery.
Any way to "detach" the save() method from Gallery and use it in MyGallery as it were defined there?
EDIT:
I forgot to say that Gallery is given and can't be changed.
You can access the __func__ attribute of the save method:
class Gallery(object):
def save(self, *args, **kwargs):
return self, args, kwargs
class MyGallery(object):
def save(self, *args, **kwargs):
return Gallery.save.__func__(self, *args, **kwargs)
# or
# save = Gallery.save.__func__
mg = MyGallery()
print mg.save('arg', kwarg='kwarg')
# (<__main__.MyGallery object at 0x04DAD070>, ('arg',), {'kwarg': 'kwarg'})
but you're better off refactoring if possible:
class SaveMixin(object):
def save(self, *args, **kwargs):
return self, args, kwargs
class Gallery(SaveMixin, object):
pass
class MyGallery(SaveMixin, object):
pass
or
def gallery_save(self, *args, **kwargs):
return self, args, kwargs
class Gallery(object):
save = gallery_save
class MyGallery(object):
save = gallery_save
I'm not sure why you are against inheritance, particularly with regard to methods. I regularly create a MixIn class that is inherited by all of my Django models.Model, and it contains all manner of useful methods for URL creation, dumps, etc., etc. I do make the methods defensive in that they use hasattr() to make sure they apply to a particular class, but doing this is a real time saver.