So I can create Django model like this:
from django.db import models
class Something(models.Model):
title = models.TextField(max_length=200)
and I can work with it like this:
thing = Something()
#set title
thing.title = "First thing"
#get title
thing.title
All works as it should but I'd like to understand HOW it works.
title = models.TextField(max_length=200)
in non-Django Python code above line defines class variable title of type models.TextField and I could access it also like this: thing.__class__.title(link)
But in Django when I create instance of Something I suddenly have a title attribute where I can get/set text. And cannot access it with thing.__class__.title So clearly when doing thing.title I'm not accessing class variable "title" but some generated attribute/property, or?
I know that fields ended up in thing._meta.fields but how? What's going on and how?
1, Does Django create property "title" behind the scenes?
2, What happened to class variable "title"?
I think its hard to beat what Django documentation has to say on this.
The Model class (see base.py) has a metaclass attribute that defines ModelBase (also in base.py) as the class to use for creating new classes. So ModelBase.new is called to create this new Example class. It is important to realise that we are creating the class object here, not an instance of it. In other words, Python is creating the thing that will eventually be bound to the Example name in our current namespace.
Basically a metaclass defines how a class itself will be created. During creation, additional attributes/methods/anything can be bound to that class. The example this stackoverflow answer gives, capitalizes all the attributes of a class
# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type):
# __new__ is the method called before __init__
# it's the method that creates the object and returns it
# while __init__ just initializes the object passed as parameter
# you rarely use __new__, except when you want to control how the object
# is created.
# here the created object is the class, and we want to customize it
# so we override __new__
# you can do some stuff in __init__ too if you wish
# some advanced use involves overriding __call__ as well, but we won't
# see this
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):
attrs = ((name, value) for name, value in future_class_attr.items() if not name.startswith('__'))
uppercase_attr = dict((name.upper(), value) for name, value in attrs)
return type(future_class_name, future_class_parents, uppercase_attr)
In a similar way, Django's metaclass for Models can digest the attributes you've applied to the class and add various useful attributes for validation/etc, including even methods and what-not.
python is extremely powerfull and permit the developer to use intrespection.
django use a lot of metaclass. and it seem that models.Model use it too. see in
django\db\models\base.py
class Model(object):
__metaclass__ = ModelBase
i think the metaclass just take the classes attributes such a the Field and for all new instance for these Model subclass,create the apropriate variable.
1) yes, django create the instance variable of property "title" automaticaly
2) in the same way, the metaclass move the fields into the meta class...
Related
I have two models in Django, one that is the base and the other that is inherited. The base model has a database field (which in Python is an attribute of the class) and the inherited model has a property that is exclusive to the Class (not of every instance created). Both can yield different things.
from django.db import models
from django.utils.decorators import classproperty
class Parent(models.Model):
somefield = models.TextField()
class Child(Parent):
#classproperty
def somefield(cls):
return 'something'
How can I create a test to ensure that all the child models created from the parent model have that class exclusive property? Because if I use hasattr() it will consider the field and the property. Something like this
assertTrue(hasattr(Child, 'somefield'))
assertFalse(hasattr(Parent, 'somefield'))
You can make type assertions on your class' attribute like this:
type(getattr(Child, "somefield"))
type(getattr(Parent, "somefield"))
The outputs should be different.
I don't know though if this a useful testcase. Your code is the source of truth, you shouldn't need to test builtins. You would rather want to instantiate specific classes and see if the output is the expected one.
I'd like to have FactoryBoy create a Django model instance for me, and then also create a temporary directory.
I've tried a few things:
class OrganizationFactory(factory.DjangoModelFactory):
class Meta:
model = Organization
some_directory = tempfile.mkdtemp
and
some_directory = tempfile.mkdtemp()
and
#factory.lazy_attribute
def some_directory(self):
return tempfile.mkdtemp()
When I try to use some_directory in my tests, the value is always None.
In order to understand what happens, the best will be to dive into factory_boy's internals.
factory_boy internals
There are separate phases in a Factory's life:
The declaration
When Python imports the module containing a class Factory declaration, that class's definition is handled to a special metaclass in factory_boy's source code.
The metaclass reads all defined class attributes and methods, analyses them, and stores them in a specific way.
Using the factory
When your code uses MyFactory(), the class starts building an instance, according to the following steps:
Evaluate the declarations: each LazyAttribute, SubFactory, etc. is asked to generate its value;
Pass the resulting parameters to the Meta.model class constructor — this provides an instance of said class;
Ask all post-generation declarations (RelatedFactory and co) to work on the generated object — note that any value returned from those declarations is thrown away
Return the instance.
Solving your issue
In your case, I believe the issue might be that some_directory is either not a valid kwarg for your model's __init__, or replaced by some magic on your model class.
The simplest way would be to work on the post-generation level:
class OrganizationFactory(factory.django.DjangoModelFactory):
class Meta:
model = Organization
#factory.post_generation
def some_directory(org, *args, **kwargs):
tmpdir = tempfile.mkdtemp()
# Attach the generated temporary directory to the generated organization.
org.some_directory = tmpdir
Beginner question here! Some time ago, I asked this question:
Parse CSV records into a list of Classes, which was also answered more technically here: How do I avoid having class data shared among instances?
I learned that, in Python classes, variables that will be defined on a per-object basis need to be declared in the __init__(self) function.
So for:
class ClassOne:
def __init__(self, datetime):
self.datetime = datetime
v = []
the variable v will hold the same data for all instances of ClassOne, whereas for:
class ClassTwo:
def __init__(self, datetime):
self.datetime = datetime
self.v = []
variable v holds individual data for each instance of ClassTwo.
However, in Django (which I'm learning now), I see the "normal" (more C++ like) behavior again for the variables:
class Post(models.Model):
title = models.CharField(max_length = 255)
Here, the variable title holds individual data for each instance of Post, despite not being defined in the __init__ function.
My basic question is Why or How does title pertain to individual class objects instead of being common to every class object, as v in ClassOne is above?
If I'm understanding this right, this means that Django classes are interpreted differently than normal Python classes? However, that conclusion doesn't make sense...
I hope that someone can help me understand this. It was my assumption previously that python code (say, a data analysis or a scientific model) could be built into a web-based service by using it's classes and routines in a Django app. If the implementation of the two different classes is different, then this would be quite difficult!
This may have been answered elsewhere. I'm not well versed in Django jango, so don't know what to search for.
The title attribute is not data. It holds a model description only; an object describing what type of information the title field should hold.
As such it is part of the class definition; individual instances of the Post class will have a title attribute that conforms to the constraints set in the models.CharField() instance on the class.
You need to build such a model to describe to Django how to build form fields and how to build a SQL table for the Post instances; both are concepts that need to have more type information than what Python normally itself needs.
Individual instances of Post are given a title attribute as well. That attribute then masks the class attribute:
p = Post(title='Some title')
print p.title # prints 'Some title'
Python looks at the instance directly first; if it does not have a title attribute, lookup would then move to the class object. But that's not needed here, the Post.title attribute is not found as the instance has a title attribute itself.
In Python itself, there is no absolute distinction between 'data' and methods, by the way. Everything in Python is an object, including classes and methods. As such, looking up an attribute on an instance can find an object there too, including methods. If an attribute lookup there fails, then Python will look for the attribute on the class and base classes, and if that fails, lookup falls back to the metaclass even.
This is where mutable attributes come in; looking up ClassOne().v fails on the instance, but succeeds on the class. Manipulating that list then alters ClassOne.v the class attribute, and looking up v on other instances once again will find the class attribute. This is how class attributes are shared, just like the methods on the class.
Django does not change the rules of the language. It does however use the language creatively. Just like class ClassTwo(...): v = [] creates one list and stores it in the class, class Post(...): title = something creates one something and stores it in the class. In this case, said something is not a char field value like "foo", it's an object which represents the concept of a char field with a max_length of 255.
Django gathers these objects representing database types, and creates (among many other things) an __init__ method that gives Post instances an attribute of the same name (which does contain an actual string value). The implementation of this is quite advanced, but firmly within the rules of the Python language - you and I can create our own Python libraries doing something similar. Anyway, since instance attributes shadow class attributes, you never notice that Post.title exists only once and isn't actually a title string. a_post_object.title always gives you the instance attribute.
As a slightly more general explanation of the relationship between class and instance variables, consider the following example that is unrelated to django models:
>>> class A(object):
... x = 2
... y = 1
...
... def __init__(self):
... self.x = 3
...
>>> A.x
2
>>> instance = A()
>>> instance.x
3
>>> instance.y
1
>>> instance.y = 4
>>> instance.y
4
>>> A.y
1
There are 2 things that I think are worth noting here. Firstly, a separate class and instance variable of the same name can exist. The class variable is only accessible directly from an instance if there is no instance variable of the same name. This is how the django models work, the class variables are fields (which are descriptions of the instance variables), the instance variables are the values for the specific instances. Using the same name for class and instance variables can be confusing, and isn't something to be done lightly. In the case of django models I think it works really well, but still can cause some headaches (I had similar questions when I first used django).
The second thing to note is that you can assign variables to an instance anywhere, it doesn't have to be in the __init__ function or even in a method of the instance's class, it can be anywhere. That is not to say that making a point of defining all instance variables in the __init__ function is a bad idea. In many cases it is a good idea.
This is a really old thread. I happen to get the same question while I'm just new to Django.
Class of 'title' is models.CharField, which seems a python descriptor. According to the Descriptor definition, 'title' is a class variable. p.title = 'xxx', there is no instance 'title'. The above statement calls the class variable title to create a hidden title for the instance. print(p.title) will just call the class variable title to return the invisible title of instance.
https://docs.python.org/3.7/howto/descriptor.html
Python cookbook chapter 8.6 also talks about the Descriptor.
Hope I'm correct and could help.
I am reading this Genshi Tutorial and see there the following example:
from formencode import Schema, validators
class LinkForm(Schema):
username = validators.UnicodeString(not_empty=True)
url = validators.URL(not_empty=True, add_http=True, check_exists=False)
title = validators.UnicodeString(not_empty=True)
As far as I understand this example, we create a new class that inherits Schema class and this class contain three methods: username, url, title. However, I am not sure about the last because before I only saw methods created with def.
Anyway, my question is not about that. I would like to know if it is possible to make the definition of the class dynamic. For example, sometimes I do not want url or title to be in the class. It seems to be doable (I just use if and assign a value to url only if-statement is satisfied.
But what if I do not know in advance what fields I would like to have in the form? For example, now I have username, url and title. But what if later I would like to have city or age. Can I do something like that:
from formencode import Schema, validators
class LinkForm(Schema):
__init__(self, fields):
for field in fields:
condition = fields[field]
field = validators.UnicodeString(condition)
I think it will not work. Is there a work around in this case?
Yes, you can add methods to an instance dynamically. No, you can't do what you want.
You can bind methods to the instance in the initializer. Unfortunately what you have there are descriptors and those must be bound to the class.
I would go the other way round—first define all form fields that might be used, and delete unneeded ones later.
Provided that you have:
from formencode import Schema, validators
class LinkForm(Schema):
username = validators.UnicodeString(not_empty=True)
url = validators.URL(not_empty=True, add_http=True, check_exists=False)
title = validators.UnicodeString(not_empty=True)
you could do either this:
def xy():
my_form = LinkForm()
del my_form.url
…
… or this:
def xy():
class CustomLinkForm(LinkForm):
pass
if …:
del CustomLinkForm.url
…
Disclaimer: I am not familiar with FormEncode, so it might depend on its inner workings which of these two versions actually works.
of course you can have a constructor with some arguments after self and these arguments will be the value for some members of your class if you have for instance
__init__(self, fields):
self.fields = []
for field in fields:
self.fields = self.fields + field
see this in Dive into Python
class FileInfo(UserDict):
"store file metadata"
def __init__(self, filename=None):
UserDict.__init__(self)
self["name"] = filename
Classes can (and should) have doc strings too, just like modules and
functions.
init is called immediately after an instance of the
class is created. It would be tempting but incorrect to call this the
constructor of the class. It's tempting, because it looks like a
constructor (by convention, init is the first method defined for
the class), acts like one (it's the first piece of code executed in a
newly created instance of the class), and even sounds like one (“init”
certainly suggests a constructor-ish nature). Incorrect, because the
object has already been constructed by the time init is called,
and you already have a valid reference to the new instance of the
class. But init is the closest thing you're going to get to a
constructor in Python, and it fills much the same role.
The first
argument of every class method, including init, is always a
reference to the current instance of the class. By convention, this
argument is always named self. In the init method, self refers to
the newly created object; in other class methods, it refers to the
instance whose method was called. Although you need to specify self
explicitly when defining the method, you do not specify it when
calling the method; Python will add it for you automatically.
init methods can take any number of arguments, and just like
functions, the arguments can be defined with default values, making
them optional to the caller. In this case, filename has a default
value of None, which is the Python null value.
Note that in the later example you learn how to deal with inherited class, calling __init()__ for this inherited class.
To answer your not-a-question about class or instance variables, see this
Variables defined in the class definition are class variables; they
are shared by all instances. To create instance variables, they can be
set in a method with self.name = value. Both class and instance
variables are accessible through the notation “self.name”, and an
instance variable hides a class variable with the same name when
accessed in this way. Class variables can be used as defaults for
instance variables, but using mutable values there can lead to
unexpected results. For new-style classes, descriptors can be used to
create instance variables with different implementation details.
Suppose we have the following code:
class A:
var = 0
a = A()
I do understand that a.var and A.var are different variables, and I think I understand why this thing happens. I thought it was just a side effect of python's data model, since why would someone want to modify a class variable in an instance?
However, today I came across a strange example of such a usage: it is in google app engine db.Model reference. Google app engine datastore assumes we inherit db.Model class and introduce keys as class variables:
class Story(db.Model):
title = db.StringProperty()
body = db.TextProperty()
created = db.DateTimeProperty(auto_now_add=True)
s = Story(title="The Three Little Pigs")
I don't understand why do they expect me to do like that? Why not introduce a constructor and use only instance variables?
The db.Model class is a 'Model' style class in classic Model View Controller design pattern.
Each of the assignments in there are actually setting up columns in the database, while also giving an easy to use interface for you to program with. This is why
title="The Three Little Pigs"
will update the object as well as the column in the database.
There is a constructor (no doubt in db.Model) that handles this pass-off logic, and it will take a keyword args list and digest it to create this relational model.
This is why the variables are setup the way they are, so that relation is maintained.
Edit: Let me describe that better. A normal class just sets up the blue print for an object. It has instance variables and class variables. Because of the inheritence to db.Model, this is actually doing a third thing: Setting up column definitions in a database. In order to do this third task it is making EXTENSIVE behinds the scenes changes to things like attribute setting and getting. Pretty much once you inherit from db.Model you aren't really a class anymore, but a DB template. Long story short, this is a VERY specific edge case of the use of a class
If all variables are declared as instance variables then the classes using Story class as superclass will inherit nothing from it.
From the Model and Property docs, it looks like Model has overridden __getattr__ and __setattr__ methods so that, in effect, "Story.title = ..." does not actually set the instance attribute; instead it sets the value stored with the instance's Property.
If you ask for story.__dict__['title'], what does it give you?
I do understand that a.var and A.var are different variables
First off: as of now, no, they aren't.
In Python, everything you declare inside the class block belongs to the class. You can look up attributes of the class via the instance, if the instance doesn't already have something with that name. When you assign to an attribute of an instance, the instance now has that attribute, regardless of whether it had one before. (__init__, in this regard, is just another function; it's called automatically by Python's machinery, but it simply adds attributes to an object, it doesn't magically specify some kind of template for the contents of all instances of the class - there's the magic __slots__ class attribute for that, but it still doesn't do quite what you might expect.)
But right now, a has no .var of its own, so a.var refers to A.var. And you can modify a class attribute via an instance - but note modify, not replace. This requires, of course, that the original value of the attribute is something modifiable - a list qualifies, a str doesn't.
Your GAE example, though, is something totally different. The class Story has attributes which specifically are "properties", which can do assorted magic when you "assign to" them. This works by using the class' __getattr__, __setattr__ etc. methods to change the behaviour of the assignment syntax.
The other answers have it mostly right, but miss one critical thing.
If you define a class like this:
class Foo(object):
a = 5
and an instance:
myinstance = Foo()
Then Foo.a and myinstance.a are the very same variable. Changing one will change the other, and if you create multiple instances of Foo, the .a property on each will be the same variable. This is because of the way Python resolves attribute access: First it looks in the object's dict, and if it doesn't find it there, it looks in the class's dict, and so forth.
That also helps explain why assignments don't work the way you'd expect given the shared nature of the variable:
>>> bar = Foo()
>>> baz = Foo()
>>> Foo.a = 6
>>> bar.a = 7
>>> bar.a
7
>>> baz.a
6
What happened here is that when we assigned to Foo.a, it modified the variable that all instance of Foo normally resolve when you ask for instance.a. But when we assigned to bar.a, Python created a new variable on that instance called a, which now masks the class variable - from now on, that particular instance will always see its own local value.
If you wanted each instance of your class to have a separate variable initialized to 5, the normal way to do it would be like this:
class Foo(object);
def __init__(self):
self.a = 5
That is, you define a class with a constructor that sets the a variable on the new instance to 5.
Finally, what App Engine is doing is an entirely different kind of black magic called descriptors. In short, Python allows objects to define special __get__ and __set__ methods. When an instance of a class that defines these special methods is attached to a class, and you create an instance of that class, attempts to access the attribute will, instead of setting or returning the instance or class variable, they call the special __get__ and __set__ methods. A much more comprehensive introduction to descriptors can be found here, but here's a simple demo:
class MultiplyDescriptor(object):
def __init__(self, multiplicand, initial=0):
self.multiplicand = multiplicand
self.value = initial
def __get__(self, obj, objtype):
if obj is None:
return self
return self.multiplicand * self.value
def __set__(self, obj, value):
self.value = value
Now you can do something like this:
class Foo(object):
a = MultiplyDescriptor(2)
bar = Foo()
bar.a = 10
print bar.a # Prints 20!
Descriptors are the secret sauce behind a surprising amount of the Python language. For instance, property is implemented using descriptors, as are methods, static and class methods, and a bunch of other stuff.
These class variables are metadata to Google App Engine generate their models.
FYI, in your example, a.var == A.var.
>>> class A:
... var = 0
...
... a = A()
... A.var = 3
... a.var == A.var
1: True