python inheritance __init__ confusion - python

I am using python 2.7 and confused about inheritance concept.
I want to make a script that can download from various manga (japanese comic site)
Every manga site uses a different method to save their file. So i have a "Manga_site" class and class called "mangacanblog" (this is a website manga).
Every manga site has a: homepage,collection,page,etc. and it's all different for each site. my question is. is this script correct to store those homepage,collection_page,etc variable? or should I use self.homepage in mangacanblog class and not in the Manga_site class?
class Manga_site:
def __init__(self,homepage,collection_page,base_manga_page,manga_title = ""):
self.homepage = homepage
self.collection_page = collection_page
self.base_manga_page = base_manga_page
self.manga_title = manga_title
class Mangacanblog(Manga_site):
def __init__(self,manga_title):
homepage = bloglink
collection_page = collectionpagelink
manga_title = manga_title.lower()
base_manga_page = basepagelink

In your Mangacanblog's __init__() function you are just setting local variables homepage, collection_page, etc, not instance variables, to make them instance variables you have to use self. , and this needs to be used in both super class as well as subclass.
But a better thing to do would be to call super(Manga_site).__init__() to let the super class handle its initialization, and then you can initialize sub class just the way you want to.
But for this, you would need to define Manga_site as a new style class, by inheriting from object class. Example -
class Manga_site(object):
def __init__(self,homepage,collection_page,base_manga_page,manga_title = ""):
self.homepage = homepage
self.collection_page = collection_page
self.base_manga_page = base_manga_page
self.manga_title = manga_title
class Mangacanblog(Manga_site):
def __init__(self,manga_title):
super(Mangacanblog, self).__init__(bloglink, collectionpagelink, basepagelink, manga_title.lower())
I have guessing you would define bloglink and collectionpagelink , before you use them in the subclass.
But this given, from the example you have given, what you are trying to achieve may be to use objects of class, and not inheritence.
Inheritence is used when the subclass has extra attributes/properties and extra methods.
You create different objects of same class if you want to store different data in them. Example -
class Manga_site:
def __init__(self,homepage,collection_page,base_manga_page,manga_title = ""):
self.homepage = homepage
self.collection_page = collection_page
self.base_manga_page = base_manga_page
self.manga_title = manga_title
mangacanblog = Manga_site('<homepage url>','<collection_page>',....)
anothermangasite = Manga_site('<another url>',....)
Then you can use these objects anyway you want to.

Related

How can I pass data into a class in python?

I am using django to create a blog editing page. However, my struggles do not involve django, rather just python. I have a class:
class EditForm(forms.Form):
def __init__(self, initcontent):
self.initcontent = initcontent
title = forms.CharField(max_length=100, label='Post Title')
short_description = forms.CharField(widget=forms.Textarea(attrs={"rows":3, "cols":100}))
content = forms.CharField(widget=CKEditorWidget(), initial=Post.objects.get(pk=initcontent).content)
and I am initialising it like this:
form = EditForm()
form.initcontent = post.pk
however I get the error:
File "C:\Users\Rayyan Admin\Documents\GitHub\shaista-s-cooking-blog\blogger\forms.py", line 34, in EditForm
content = forms.CharField(widget=CKEditorWidget(), initial=Post.objects.get(pk=initcontent).content)
NameError: name 'initcontent' is not defined
How do i pass initcontent into the class?
Hi your indenting is off so I'm not sure if that's a mistake in formatting here or causing issues with your code.
Anyways I think what you want is:
class EditForm():
def __init__(self, initcontent):
self.initcontent = initcontent
form = EditForm(post.pk)
Whenever you make an instance of a class, you can pass your data into it if you have defined a constructor. That is the role of a constructor. In your case, you have defined a constructor with initcontent as a parameter. So you can do it like this -
form = EditForm(whatever you need to pass)
This will do.

Add a dynamically generated Model to a models.py in an Django project

I am generating a Django model based on an abstract model class AbstractAttr and a normal model (let's say Foo).
I want my foo/models.py to look like this:
from bar.models import Attrs
# ...
class Foo(models.Model):
....
attrs = Attrs()
In the Attrs class which mimics a field I have a contribute_to_class that generates the required model using type(). The generated model c is called FooAttr.
Everything works. If I migrate, I see FooAttr appear in the proper table.
EXCEPT FOR ONE THING.
I want to be able to from foo.models import FooAttr. Somehow my generated FooAttr class is not bound to the models.py file in which it is generated.
If I change my models.py to this:
class Foo(models.Model):
# ...
FooAttr = generate_foo_attr_class(...)
it works, but this is not what I want (for example, this forces the dev to guess the generate class name).
Is what I want possible, define the class somewhat like in the first example AND bind it to the specific models.py module?
The project (pre-Alpha) is here (in develop branch):
https://github.com/zostera/django-mav
Some relevant code:
def create_model_attribute_class(model_class, class_name=None, related_name=None, meta=None):
"""
Generate a value class (derived from AbstractModelAttribute) for a given model class
:param model_class: The model to create a AbstractModelAttribute class for
:param class_name: The name of the AbstractModelAttribute class to generate
:param related_name: The related name
:return: A model derives from AbstractModelAttribute with an object pointing to model_class
"""
if model_class._meta.abstract:
# This can't be done, because `object = ForeignKey(model_class)` would fail.
raise TypeError("Can't create attrs for abstract class {0}".format(model_class.__name__))
# Define inner Meta class
if not meta:
meta = {}
meta['app_label'] = model_class._meta.app_label
meta['db_tablespace'] = model_class._meta.db_tablespace
meta['managed'] = model_class._meta.managed
meta['unique_together'] = list(meta.get('unique_together', [])) + [('attribute', 'object')]
meta.setdefault('db_table', '{0}_attr'.format(model_class._meta.db_table))
# The name of the class to generate
if class_name is None:
value_class_name = '{name}Attr'.format(name=model_class.__name__)
else:
value_class_name = class_name
# The related name to set
if related_name is None:
model_class_related_name = 'attrs'
else:
model_class_related_name = related_name
# Make a type for our class
value_class = type(
str(value_class_name),
(AbstractModelAttribute,),
dict(
# Set to same module as model_class
__module__=model_class.__module__,
# Add a foreign key to model_class
object=models.ForeignKey(
model_class,
related_name=model_class_related_name
),
# Add Meta class
Meta=type(
str('Meta'),
(object,),
meta
),
))
return value_class
class Attrs(object):
def contribute_to_class(self, cls, name):
# Called from django.db.models.base.ModelBase.__new__
mav_class = create_model_attribute_class(model_class=cls, related_name=name)
cls.ModelAttributeClass = mav_class
I see you create the model from within models.py, so I think you should be able to add it to the module's globals. How about this:
new_class = create_model_attribute_class(**kwargs)
globals()[new_class.__name__] = new_class
del new_class # no need to keep original around
Thanks all for thinking about this. I have updated the source code of the project at GitHub and added more tests. See https://github.com/zostera/django-mav
Since the actual generation of the models is done outside of foo/models.py (it takes place in mav/models.py, it seems Pythonically impossible to link the model to foo/models.py. Also, after rethinking this, it seems to automagically for Python (explicit is better, no magic).
So my new strategy is to use simple functions, a decorator to make it easy to add mav, and link the generated models to mac/attrs.py, so I can universally from mav.attrs import FooAttr. I also link the generated class to the Foo model as Foo._mav_class.
(In this comment, Foo is of course used as an example model that we want to add model-attribute-value to).

python django make a subclass use the parents table

Hoi, this is my first post and I am pretty new to django.
[Edit: changed "from" to "mfrom"]
I have a generic class like
class Message(models.Model):
mfrom = models.TextField()
text = models.TextField()
def beautify(self, text):
'''replace emoticons with images'''
return text
def save(self, *args, **kwargs):
self.text = self.beautify(self.text)
super(Message, self).save(*args, **kwargs)
and I have a few sources where messages are coming from that need different handling, some (like XMPP) will come from non HTTP request sources, but external scripts.
So I thought I'd make subclasses of Message for the different types like
class MessageXMPP(Message):
def load_from_XMPP(self, xmppmsg):
self.mfrom = xmppmsg.mfrom
self.text = xmppmsg.text
class MessageJSON(Message):
def load_from_JSON(self, jsonmsg):
self.mfrom = jsonmsg.mfrom
self.text = jsonmsg.text
If I now call the save() method of the above two classes django tries to save it to the MessageXMPP resp. MessageJSON tables, while I want the data to be stored in the Message table (and not have MessageXMPP resp. MessageJSON tables created at all).
Is there a way to not create a Message object and copy the values over, but have the subclasses write to the Message table?
I don't really understand why you have separate model classes here. You should really just have one class with the different methods. Even better, since these are creation methods, you should define a custom Manager which returns the instantiated Message.
However, if you insist on having separate classes, you should make them proxy models so that they do not reference their own tables:
class MessageJSON(Message):
class Meta:
proxy = True

Making two classes reference eachother

I'm trying to make a text adventure where different "place" classes can point to eachother.
For instance, I have a Manager class that has a reference to each place. Then I have a Home class, and a Club class, with references to eachother through manager. The problem is that I can't instantiate them due to the circular reference.
Here's how I solved it, but it's ugly, because I have to create the places member inside of a method instead of __init__.
class Manager:
def __init__(self):
self.home = Home(self)
self.club = Club(self)
class Home:
def __init__(self, manager):
self.places = {}
self.manager = manager
def display_plot_and_get_option (self):
print "where do you want to go?"
return 'club' #get this from user
def get_next_place(self, place_name):
self.places = { #THIS IS THE BAD PART, which should be in __init__ but can't
'home':self.manaer.home
'club':self.manaer.club }
return self.places[place_name]
class Club:
#similar code to Home
pass
manager = Manager()
while (True):
place_name = manager.current_place.display_plot_and_get_option()
manager.current_place = manager.current_place.get_next_place(place_name)
In c++ I would set my dict up in the constructor, where it should be, and it would use the pointer of the Manager's home or club members, since I only want 1 instance of each place. How can I do this in python?
edit: expanded code example
You can just have a dictionary that holds the references, and call the methods straight from the Manager (which shouldn't really be named Manager, as it does not serve that purpose now) instance.
class Home(object):
pass
class Club(object):
pass
PLACES = {
'home': Home(),
'club': Club()
}
class Manager(object):
def display_plot_and_get_option(self):
return raw_input('Where do you want to go?')
def get_next_place(self, place_name):
return PLACES[place_name]
m = Manager()
while 1:
place_name = m.display_plot_and_get_option()
m.get_next_place(place_name)
Assuming that Home and Club are just a couple of the many places you plan to include in your game, it would probably be advantageous to create a Place class. Specific classes can either inherit from Place or have a name as a data member. Then you can model connections with a tree or graph.

python static class with static method that uses self?

I'm doing a database insert script in pycassa. I want to set up a public static class that defines some variables that will get used a lot by other functions later on. Heres what I have...
class ks_refs():
pool = ConnectionPool('TweetsKS')
user_name_cf = self.cf_connect('UserName')
user_tweet_cf = self.cf_connect('UserTweet')
def cf_connect(column_family):
cf = pycassa.ColumnFamily(self.pool, column_family)
return cf
I haven't even tried to run this yet because I'm sure it wont work. You can see I want this static variable 'pool' first, and then set up user_name_cf and user_tweet_cf (and some more later) using the cf_connect method which needs 'pool' to work.
I know I could put that method outside the class, or I could have this non-static and make an instance of it, but I want to try this because this is what I really want (before I was just using globals but I think a static class holding all this is the best idea)
I think you want to have a class method instead:
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
Now you can refer to the pool defined on your class with ease.
Your user_name_cf and user_tweet_cf 'attributes' will not work, however. You can add these after having created the class definition:
class ks_refs():
pool = ConnectionPool('TweetsKS')
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
user_name_cf = ks_refs.cf_connect('UserName')
user_tweet_cf = ks_refs.cf_connect('UserTweet')
where they are then module-level constants, or you can add them to the class as attributes after the fact:
ks_refs.user_name_cf = ks_refs.cf_connect('UserName')
ks_refs.user_tweet_cf = ks_refs.cf_connect('UserTweet')

Categories

Resources