I have a class called resources and I have defined one method called get_connect. I want to use the data of which get_connect returns to the other classes. I need at least three classes and I use the data of get_connect and I have to parse that data. To implement this I have written the code below
class resources:
#staticmethod
def get_connect():
return 1 + 2
class Source1(resources):
def __init__(self):
self.response = resources.get_connect()
def get__details1(self):
print(self.response)
class Source2(resources):
def __init__(self):
self.response = resources.get_connect()
def get_details2(self):
print(self.response)
class Source3(resources):
def __init__(self):
self.response = resources.get_connect()
def get__detail3(self):
print(self.response)
source1 = Source1()
source2 = Source2()
source3 = Source3()
source1.get__details1()
source2.get_details2()
source3.get__detail3()
But the problem with the code is for every class in init method I am calling the get_connect method. I don't want to repeat the code. I need help for avoiding redundancy which I have asked below
Is there any way I can call get_connect in one place and use it for other classes maybe a decorator or anything? if yes how can I?
While creating objects also I am calling each class and calling each method every time. is there a way to use any design pattern here?
If anyone helps me with these oops concepts it will be useful.
First of all, is there any reason why you are using get_connect method as static?
Because what you can do here is declare it in the parent class:
class resources:
def __init__(self):
self.response = self.get_connect()
def get_connect(self):
return 1 + 2
This way you do not need to define the __init__ method on every class, as it will be automatically inherited from the parent.
Regarding the second question, it really depends on the context, but you can use a strategy pattern in order to retrieve the class that you require to call. For this rename the method of get details into the same for each of the classes, as basically they're used for the same purpose, but changed on the context of the class implementation:
class Source1(resources):
def get_details(self):
print(self.response)
class Source2(resources):
def get_details(self):
print(self.response)
class Source3(resources):
def get_details(self):
print(self.response)
classes = {
"source_1": Source1,
"source_2": Source2,
"source_3": Source3
}
source_class = classes["source_1"]
source = source_class()
source.get_details()
Hope this helped!
This might sound like a duplicate, but I don't think it is.
I need to do something a bit similar to what the asker did there : django model polymorphism with proxy inheritance
My parent needs to implement a set of methods, let's call them MethodA(), MethodB(). These methods will never be used directly, they will always be called through child models (but no, abstract class is not the way to go for various reasons).
But this is where it becomes trickier :
Each child model inherits from a specific module (moduleA, moduleB), they all implement the same method names but do something different. The calls are made through the parent model, and are redirected to the childs depending on the values of a field
Since I guess it's not very clear, here is some pseudo-code to help you understand
from ModuleA import CustomClassA
from ModuleB import CustomClassB
class ParentModel(models.Model):
TYPE_CHOICES = (
('ChildModelA', 'A'),
('ChildModelB', 'B'),
)
#some fields
type = models.CharField(max_length=1, choices=TYPE_CHOICES)
def __init__(self, *args, **kwargs):
super(ParentModel, self).__init__(*args, **kwargs)
if self.type:
self.__class__ = getattr(sys.modules[__name__], self.type)
def MethodA():
some_method()
def MethodB():
some_other_method()
class ChildModelA(ParentModel, CustomClassA):
class Meta:
proxy = True
class ChildModelB(ParentModel, CustomClassB):
class Meta:
proxy = True
In ModuleA :
class CustomClassA():
def some_method():
#stuff
def some_other_method():
#other stuff
In ModuleB :
class CustomClassB():
def some_method():
#stuff
def some_other_method():
#other stuff
Right now, the problem is that the class change works, but it does not inherit from ChildModelA or B.
Is this even possible? If yes, how can I make it work, and if no, how could I do this elegantly, without too much repetition?
A proxy model must inherit from exactly one non-abstract model class. It seems that both CustomClass and ParentModel are non-abstract. I would suggest to make CustomClass abstract since no attributes are defined.
This is explained in dept here: https://docs.djangoproject.com/en/3.2/topics/db/models/#proxy-models
I have a settings object that contains some generic settings. These settings will change for each user. I'm wondering what would be the best way to code this. My current method is this:
class Settings(object):
def __init__(self, user=None):
if user and not isinstance(user, users.User):
raise TypeError('must be a User object')
self.user = user
#property
def title(self):
if self.user:
return 'user setting'
return 'generic setting'
Given that there will be a few methods in Settings, having to run that if statement each time kinda sucks.
I was considering having a UserSettings class that extends Settings to override the defaults and provide the user specific settings. Though, I've heard that overriding methods is bad OOP design. Which leads me to option 2...
I then thought of creating UserSettings but it won't extend Settings. It'll instead wrap it and I'll have something like:
class UserSettings(object):
def __init__(self, user=None):
if user and not isinstance(user, users.User):
raise TypeError('must be a User object')
self.user = user
self.settings = Settings()
#property
def title(self):
return 'user setting'
So I can then do:
print user_settings.title # get the user title
print user_settings.settings.title # get the generic title
How should I code this?
Overriding methods is not only not bad OOP design, it's the basis for subtype polymorphism, which is core to OOP, and a common way to get rid of the need for such conditional checks.
There are certainly times when you should prefer composition to inheritance, but it's not clear from your description that there's anything wrong with making this a subclass.
My application uses class inheritance to minimize repetition across my models. My models.py looks kind of like this:
class BaseModel(models.Model):
title = models.CharField(max_length=100)
pub_date = models.DateField()
class Child(BaseModel):
foo = models.CharField(max_length=20)
class SecondChild(BaseModel):
bar = models.CharField(max_length=20)
Now most of the time, my views and templates only deal with instances of Child or SecondChild. Once in a while, however, I have a situation where I have an instance of BaseModel, and need to figure out which class is inheriting from that instance.
Given an instance of BaseModel, let's call it base, Django's ORM offers base.child and base.secondchild. Currently, I have a method that loops through all of them to figure it out. It would look something like this:
class BaseModel(models.Model):
...
def get_absolute_url(self):
url = None
try:
self.child
url = self.child.get_absolute_url()
except Child.DoesNotExist:
pass
if not url:
try:
self.secondchild
url = self.secondchild.get_absolute_url()
except SecondChild.DoesNotExist:
pass
if not url:
url = '/base/%i' % self.id
return url
That is hopelessly ugly, and gets uglier with every additional child class I have. Does anybody have any ideas on a better, more pythonic way to go about this?
Various forms of this question pop up here regularly. This answer demonstrates a generic way to "cast" a parent type to its proper subtype without having to query every subtype table. That way you wouldn't need to define a monster get_absolute_url on the parent which covers all the cases, you'd just convert to the child type and call get_absolute_url normally.
I haven't messed with Django inheitance much, so I suppose you can't override get_absolute_url() in the model classes?
Perhaps the visitor pattern could help if there are lot of functions that need this in many different places.
I haven't tested this, but it might be worth tinkering with:
def get_absolute_url(self):
subclasses = ('child', 'secondchild', )
for subclass in subclasses:
if hasattr(self, subclass):
return getattr(self, subclass).get_absolute_url()
return '/base/%i' % self.id
This was fixed in Django 1.9 with form_kwargs.
I have a Django Form that looks like this:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(queryset=ServiceOption.objects.none())
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1, widget=custom_widgets.SmallField())
def __init__(self, *args, **kwargs):
affiliate = kwargs.pop('affiliate')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["option"].queryset = ServiceOption.objects.filter(affiliate=affiliate)
I call this form with something like this:
form = ServiceForm(affiliate=request.affiliate)
Where request.affiliate is the logged in user. This works as intended.
My problem is that I now want to turn this single form into a formset. What I can't figure out is how I can pass the affiliate information to the individual forms when creating the formset. According to the docs to make a formset out of this I need to do something like this:
ServiceFormSet = forms.formsets.formset_factory(ServiceForm, extra=3)
And then I need to create it like this:
formset = ServiceFormSet()
Now how can I pass affiliate=request.affiliate to the individual forms this way?
Official Document Way
Django 2.0:
ArticleFormSet = formset_factory(MyArticleForm)
formset = ArticleFormSet(form_kwargs={'user': request.user})
https://docs.djangoproject.com/en/2.0/topics/forms/formsets/#passing-custom-parameters-to-formset-forms
I would use functools.partial and functools.wraps:
from functools import partial, wraps
from django.forms.formsets import formset_factory
ServiceFormSet = formset_factory(wraps(ServiceForm)(partial(ServiceForm, affiliate=request.affiliate)), extra=3)
I think this is the cleanest approach, and doesn't affect ServiceForm in any way (i.e. by making it difficult to subclass).
I would build the form class dynamically in a function, so that it has access to the affiliate via closure:
def make_service_form(affiliate):
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(
queryset=ServiceOption.objects.filter(affiliate=affiliate))
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1,
widget=custom_widgets.SmallField())
return ServiceForm
As a bonus, you don't have to rewrite the queryset in the option field. The downside is that subclassing is a little funky. (Any subclass has to be made in a similar way.)
edit:
In response to a comment, you can call this function about any place you would use the class name:
def view(request):
affiliate = get_object_or_404(id=request.GET.get('id'))
formset_cls = formset_factory(make_service_form(affiliate))
formset = formset_cls(request.POST)
...
This is what worked for me, Django 1.7:
from django.utils.functional import curry
lols = {'lols':'lols'}
formset = modelformset_factory(MyModel, form=myForm, extra=0)
formset.form = staticmethod(curry(MyForm, lols=lols))
return formset
#form.py
class MyForm(forms.ModelForm):
def __init__(self, lols, *args, **kwargs):
Hope it helps someone, took me long enough to figure it out ;)
I like the closure solution for being "cleaner" and more Pythonic (so +1 to mmarshall answer) but Django forms also have a callback mechanism you can use for filtering querysets in formsets.
It's also not documented, which I think is an indicator the Django devs might not like it as much.
So you basically create your formset the same but add the callback:
ServiceFormSet = forms.formsets.formset_factory(
ServiceForm, extra=3, formfield_callback=Callback('option', affiliate).cb)
This is creating an instance of a class that looks like this:
class Callback(object):
def __init__(self, field_name, aff):
self._field_name = field_name
self._aff = aff
def cb(self, field, **kwargs):
nf = field.formfield(**kwargs)
if field.name == self._field_name: # this is 'options' field
nf.queryset = ServiceOption.objects.filter(affiliate=self._aff)
return nf
This should give you the general idea. It's a little more complex making the callback an object method like this, but gives you a little more flexibility as opposed to doing a simple function callback.
I wanted to place this as a comment to Carl Meyers answer, but since that requires points I just placed it here. This took me 2 hours to figure out so I hope it will help someone.
A note about using the inlineformset_factory.
I used that solution my self and it worked perfect, until I tried it with the inlineformset_factory. I was running Django 1.0.2 and got some strange KeyError exception. I upgraded to latest trunk and it worked direct.
I can now use it similar to this:
BookFormSet = inlineformset_factory(Author, Book, form=BookForm)
BookFormSet.form = staticmethod(curry(BookForm, user=request.user))
As of commit e091c18f50266097f648efc7cac2503968e9d217 on Tue Aug 14 23:44:46 2012 +0200 the accepted solution can't work anymore.
The current version of django.forms.models.modelform_factory() function uses a "type construction technique", calling the type() function on the passed form to get the metaclass type, then using the result to construct a class-object of its type on the fly::
# Instatiate type(form) in order to use the same metaclass as form.
return type(form)(class_name, (form,), form_class_attrs)
This means even a curryed or partial object passed instead of a form "causes the duck to bite you" so to speak: it'll call a function with the construction parameters of a ModelFormClass object, returning the error message::
function() argument 1 must be code, not str
To work around this I wrote a generator function that uses a closure to return a subclass of any class specified as first parameter, that then calls super.__init__ after updateing the kwargs with the ones supplied on the generator function's call::
def class_gen_with_kwarg(cls, **additionalkwargs):
"""class generator for subclasses with additional 'stored' parameters (in a closure)
This is required to use a formset_factory with a form that need additional
initialization parameters (see http://stackoverflow.com/questions/622982/django-passing-custom-form-parameters-to-formset)
"""
class ClassWithKwargs(cls):
def __init__(self, *args, **kwargs):
kwargs.update(additionalkwargs)
super(ClassWithKwargs, self).__init__(*args, **kwargs)
return ClassWithKwargs
Then in your code you'll call the form factory as::
MyFormSet = inlineformset_factory(ParentModel, Model,form = class_gen_with_kwarg(MyForm, user=self.request.user))
caveats:
this received very little testing, at least for now
supplied parameters could clash and overwrite those used by whatever code will use the object returned by the constructor
Carl Meyer's solution looks very elegant. I tried implementing it for modelformsets. I was under the impression that I could not call staticmethods within a class, but the following inexplicably works:
class MyModel(models.Model):
myField = models.CharField(max_length=10)
class MyForm(ModelForm):
_request = None
class Meta:
model = MyModel
def __init__(self,*args,**kwargs):
self._request = kwargs.pop('request', None)
super(MyForm,self).__init__(*args,**kwargs)
class MyFormsetBase(BaseModelFormSet):
_request = None
def __init__(self,*args,**kwargs):
self._request = kwargs.pop('request', None)
subFormClass = self.form
self.form = curry(subFormClass,request=self._request)
super(MyFormsetBase,self).__init__(*args,**kwargs)
MyFormset = modelformset_factory(MyModel,formset=MyFormsetBase,extra=1,max_num=10,can_delete=True)
MyFormset.form = staticmethod(curry(MyForm,request=MyFormsetBase._request))
In my view, if I do something like this:
formset = MyFormset(request.POST,queryset=MyModel.objects.all(),request=request)
Then the "request" keyword gets propagated to all of the member forms of my formset. I'm pleased, but I have no idea why this is working - it seems wrong. Any suggestions?
I spent some time trying to figure out this problem before I saw this posting.
The solution I came up with was the closure solution (and it is a solution I've used before with Django model forms).
I tried the curry() method as described above, but I just couldn't get it to work with Django 1.0 so in the end I reverted to the closure method.
The closure method is very neat and the only slight oddness is that the class definition is nested inside the view or another function. I think the fact that this looks odd to me is a hangup from my previous programming experience and I think someone with a background in more dynamic languages wouldn't bat an eyelid!
I had to do a similar thing. This is similar to the curry solution:
def form_with_my_variable(myvar):
class MyForm(ServiceForm):
def __init__(self, myvar=myvar, *args, **kwargs):
super(SeriveForm, self).__init__(myvar=myvar, *args, **kwargs)
return MyForm
factory = inlineformset_factory(..., form=form_with_my_variable(myvar), ... )
I'm a newbie here so I can't add comment. I hope this code will work too:
ServiceFormSet = formset_factory(ServiceForm, extra=3)
ServiceFormSet.formset = staticmethod(curry(ServiceForm, affiliate=request.affiliate))
as for adding additional parameters to the formset's BaseFormSet instead of form.
based on this answer I found more clear solution:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(
queryset=ServiceOption.objects.filter(affiliate=self.affiliate))
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1,
widget=custom_widgets.SmallField())
#staticmethod
def make_service_form(affiliate):
self.affiliate = affiliate
return ServiceForm
And run it in view like
formset_factory(form=ServiceForm.make_service_form(affiliate))