use one function with muliple classes

hello Django Pals,
Thanks In Advance for any help.

i want to use one function for default Image instead of repeating many times
Classes:

class Category

class Product

class Catalog

Function:

def category_default_image():
	return 'Defaults/DefaultCategoryImage.png'

is there any way to iterate through classes inside the function to make different paths for each class?

Thanks

It’s not clear what you’re looking to achieve here.

What I’m getting from what you’ve written here is that you want to have a category_default_image function in each of those classes but with a different return value for each class - and without defining the category_default_image in every class.

Am I understanding you correctly?

1 Like

i have the same function in each class but i have to repeat it with different name for each class one for product and one for categories and one for catalog,
the goal to return different path for each class instead of repeating the same function with different namein models.py

as example:

def default_image():
         for class product 
               return 'Defaults/DefaultProductImage.png'
         for class catalog
	           return 'Defaults/DefaultCatalogImage.png'
         for class category
	            return 'Defaults/DefaultCategoryImage.png'
	

Every solution I can think of for this is actually going to involve more code and be less clear. I don’t see anything being gained or improved by worrying about this.

My suggestion is to go ahead and define the function in each model and continue on with your project.

1 Like

As it seems to be a variable exclusive to each class (and theere is nothing more complicated):

class MyMixin():
    default_image = ''

    def my_method(self):
        return self.default_image

class MyFirstClass(MyMixin):

        default_image = 'your/string.png'

I am only using the mixin to illustrate that my_method could be more sophisticated. If you don’t need that, then just get the default_image value directly from the class.

MyFirstClass().default_image
1 Like

Like I said - you’re adding four lines of code, and the use of a class and a mixin, to save three lines of code.

I fail to see where that is in any way an improvement over the simple method. It is more code (not significantly more) and (admittedly, arguably) the use of the extra class and Mixin is less clear than the straight-forward approach.

1 Like

Thanks Buddy it is really useful for me and new ideas, thank you so much.

thanks man, a lot i think it is useful also to keep code clean and simple .

If I am correctly reading what AhmdMWddh initially wrote, then he is repeating the seven line method three times in his three classes, which makes 21 lines of code to maintain.

My mixin is four lines, and requires one line in each class, or two lines at most, if you count adding the mixin as a parameter to the class – a total of ten lines. So, significantly less code, and much DRYer. Because it is much DRYer, it is also much easier to maintain.

I am also making the point that one can just add default_image as a variable to the class, and that is only one line per class (total three lines), and use that directly, as any of:

MyClass.default_image
MyClass().default_image
self.default_image

Rather than:

MyClass().my_method()
self.my_method()

NB, for those struggling with classes and self, you can’t address self unless you first initialise the class (by adding the () and any parameters). So in this case, because my_method refers to self.default_image, you cannot do MyClass.my_method(), you have to either:

my_class = MyClass() '''initialise the class, rather than make a copy of it'''
my_class.my_method()

or

MyClass().my_method() '''initialise the class and execute the method'''

I think it only makes sense to use a method here if there is actually some logic in the method, ie it is not returning the same string evey time it is called. If you are returning the same string on every call, then just use the variable in the class.

I’m a relatively noob to Python/Django, but I can see that using the mixin is a really powerful technique, so I’d expect anyone else unfamiliar/inexperienced with Python to also grasp that, or ask for a further explanation.

Repeating the same method in three different classes is really poor technique, that should be pointed out, and the alternatives given.

1 Like

You may have been reading what he originally wrote as his code correctly, but not his intent.

What you are replacing is:

def default_image(self):
    return "Defaults/DefaultProductImage.png"

when that function exists in model Product, with the corresponding changes in the other two models.

Six lines total.

Actually it’s not.

While DRY is a very nice and useful principle, it’s just that - a principle and not a hard-and-fast rule or requirement. Part of the skill of being a software developer comes from knowing these principles, and recognizing where those principles don’t apply, and under what circumstances to ignore them.

If that is all the method default_image does, then a method is not required, a variable, in the class does this:

default_image = 'Defaults/DefaultProductImage.png'

That’s three lines, and was in my first post, and is about as simple as you can get. I addressed the subject of the question “use one function with multiple classes” via the mixin usage, and the practical point of the question with the variable, noting that you wouldn’t really want to use a method (ie the mixin) if all you were doing was consistently delivering the same string.

Either way, I hope the OP learnt something about reusing code.

1 Like

And that depends upon how this is going to be used - which isn’t clear from the original request.

If the usage of this only requires a literal, the direct answer does work and is the simplest most direct result.

However, there are cases where there are other methods that don’t take literals - you must pass a callable, and in those cases a function returning that value is necessary.

Absolutely agree there, and I also believe this additional conversation adds to the educational element here…

1 Like

Ok, so to round out the educational element… :grinning:

One would suspect that the OP is in control of whatever is accessing default_image. It is perfectly reasonable to suspect that whatever that is, it is expecting a method in the class, ie a callable.

class MyClass:

    def default_image(self):
        return 'the_image.png'

    # method that references 'default_image'
    def grab_the_image(self):
        …
        return self.default_image()

So, to access the output of default_image:

my_img = MyClass().default_image()

Or, we suspect the OP to be using it within a class:

my_img = self.default_image()

Since, in this case, default_image is returning a string and is not completing any processing/logic in the output of that string, we don’t actually need a method/callable to access that value, we can simply use a variable/literal:

class MyClass:

    default_image = 'the_image.png'

Then to access default_image:

my_img = MyClass().default_image #ie no '()' 

Or even, without initialising the class:

my_img = MyClass.default_image #ie no '()' on class either

Or, in the case where some other method in the class wants the default_image string:

class MyClass:

    default_image = 'the_image.png'

    …

    # method that references 'default_image'
    def grab_the_image(self):
        …
        return self.default_image

The short verion of which is:

If you are accessing a method, then you need to add the () to the call, in order to execute that method (otherwise you’ll just get a copy of the method), if you are accessing a literal, then you don’t use the ().

If you get that mixed up, then you’ll end up with a lot of errors.

If you are changing the object in the class from a method to a literal, or vice versa, then you will also need to update all of the references.

1 Like

In the context of the original discussion, and the type and nature of the sample data being supplied, my guess is that this function is intended to be used in a FileField as the callable being supplied to the upload_to attribute. That’s the most common case I’m aware of where you might want to supply a callable containing a path and file name where those values depend upon the type of the class.

1 Like

@KenWhitesell , @typonaut

thank you so much for this rich information so useful of course grateful for you my friends.

about my intention of my code, i have in Product and Catalog and Category classes and each of them has an ImageField, and each ImageField has 2 functions default_image() and other upload image()
default_image() will return a string path for the default image, and upload_image() this function have 2 lines logic to rename the input image and its extension also and that for each Class Product and Catalog and Category.
also this function will be used in ImageField Options upload_to and default.