I'm trying to create a class/static method within a class. I need SignInForm to have the defined instance variables, as they are rendered by Django's template. How does one call a method within a class from an instance variable? My objective is to update each variable with the custom widget for creating a consistent style.
class SignInForm(forms.Form):
@classmethod
def get_text_input_with_attributes():
return forms.TextInput(attrs= {'class':'form-style'})
first_name = forms.CharField(max_length=50,required=True)
first_name.widget = SignInForm.get_text_input_with_attributes()
last_name = forms.CharField(max_length=50,error_messages={'required': ''})
last_name.widget = SignInForm.get_text_input_with_attributes()
....lots of other custom fields
Error:
name 'SignInForm' is not defined
First, the short version:
You can't call methods of a class—even classmethods and staticmethods—while you're in the middle of defining that class, at least not easily.
So, what can you do? Well, really, you don't want a class method or a static method here. You want a regular old function. Like this:
class Spam(object):
def _func():
return 42
class_attr = _func()
del _func
After the class is defined, _func
would be an instance method—and an un-callable instance method, since it doesn't take a self
. (That's why I prefixed it with an underscore, and also del
'd it, to make it harder to accidentally call it later…)
But while it's being defined, it's a normal function, and can be called as such.
I should mention that usually, wanting to do this is a sign that there's something off about your design, and the thing you're trying to write as a classmethod or staticmethod should actually be a method of a base class, or a free function or a class constructor, or maybe even a metaclass method.
As David Sanders' answer explains, the specific thing you're trying to do is common enough that there's an idiomatic way to write it: as a class constructor for a TextField
subclass.
How does this work?
Clearly, while you're in the middle of executing the Spam
class definition, there is nothing called Spam
, so you definitely can't call Spam._func
.
But why can you call _func
? You have to understand how class definitions are executed. Oversimplifying a bit: Python creates an empty global dictionary, runs all the code inside the class
definition as if it were a script, then it goes back to the real globals and runs Spam = type('Spam', (object,), that_global_dict)
. So when we do class_attr = _func()
, we're inside that temporary global environment, and _func
is a function in that environment, so we can call it.
So, why can't we do this with a classmethod
or staticmethod
?
For one thing, you need a cls
object to call a classmethod
, and we don't have one.
For another, classmethod
and staticmethod
objects aren't callable. Function objects are callable as themselves, and they're also descriptors that can be used to construct bound methods. Class and static methods are not callable, they're just descriptors that can be used to construct bound methods in special ways (bound to a class or to nothing, instead of to an instance).
So, what if you wanted to write something that was usable as a class-definition-time function, and also as a static method later? The simplest way is:
class Spam(object):
def _func():
return 42
smeth = staticmethod(_func)
class_attr = func()
del _func
A decorator like @staticmethod
just does, in effect, _func = staticmethod(_func)
. We can do the same thing, but give the result a different name, and now we've got a static method, while still having the original function to call directly.
While abernet's answer does a good job of explaining why you were getting that error, the idiomatic way to do this with django would be something like this:
from django import forms
class SignInFormCharField(forms.CharField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('widget', forms.TextInput(attrs={'class': 'form-style'}))
super(SignInFormCharField, self).__init__(*args, **kwargs)
class SignInForm(forms.Form):
first_name = SignInFormCharField(max_length=50, required=True)
last_name = SignInFormCharField(max_length=50, error_messages={'required': ''})
# ...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.