Answer
As Sergey pointed out, class Model(**kwargs) is invalid, and is a typo in Django documentation.
The "class" part comes from the markup they used when they wrote it.
So, what they actually meant in the Django documentation is:
Creating objects
To create a new instance of a model, just instantiate it like any
other Python class:
Model(**kwargs)
The keyword arguments are simply the names of the fields you’ve
defined on your model. Note that instantiating a model in no way
touches your database; for that, you need to save().
Original question
I found the following while reading the Django Docs about Model instances:
Creating objects
To create a new instance of a model, just instantiate it like any
other Python class:
class Model(**kwargs)
The keyword arguments are simply the names of the fields you’ve
defined on your model. Note that instantiating a model in no way
touches your database; for that, you need to save().
What is the difference between these two codes?
class Model(**kwargs)
new_model = Model(**kwargs)
I know the second one creates a new instance of the class Model, with kwargs.
Is the first one different from it? To me, it seems like it rather redefines the Model class.
class Model(**kwargs) is not a valid Python syntax, the latter would look like
class Model(SomeBaseClass):
pass
Judging by the formatting (the line looks like a subheading), this must be a mistake in the Django documentation.
If you look at the Sphinx source of the page, you'll see that the "class" thing is actually a part of Sphinx markup. What they meant is
To create a new instance of a model, just instantiate it like any
other Python class:
Model(**kwargs)
The keyword arguments are simply the names of the fields you've
defined on your model.
The first line defines a class.
The second line defines an instance of a class.
Related
I have a next model
class MyClass(models.Model):
# fields
When I try to get __class__ it returns 'ModelBase'.
What I actually need is to find a method of how to get a class name for models.MyClass.
Is it possible without having an instance of it?
Updated:
Sorry guys, I put it wrong, what I wanted to ask was a bit different. I am probably to tired.
This questions actually duplicates:
Get class name of django model
MyClass.__name__ should return the name of the class as a string.
.__name__ in general is the best way to get variables and functions names.
Try MyClass.__name__.
Django models are derived from the ModelBase, which is the Metaclass for all models.
I got two models, for example:
Parent(models.Model):
mytext= models.Chafield(max_lenght=250, blank=True)
Child(Parent):
mytext_comment=models.Chafield(max_lenght=250)
But in child I want mytext to be obligatory.
Do it will be sufficient to invoke mytext.blank=False in child __init__ ?
Caution this are not abstract methods because I want to be able to use Manager on Parent (Parent.objects.all() for example)
I don't think its possible. From Django Documentation:
This restriction only applies to attributes which are Field instances.
Normal Python attributes can be overridden if you wish. It also only
applies to the name of the attribute as Python sees it: if you are
manually specifying the database column name, you can have the same
column name appearing in both a child and an ancestor model for
multi-table inheritance (they are columns in two different database
tables).
PS: I tried to like you suggested, but I get error like unicode object has no attribute blank
Hmm you can try this solution:
Parent(models.Model):
mytext= models.Chafield(max_lenght=250, blank=True)
Child(Parent):
mytext_comment=models.Chafield(max_lenght=250)
Child._meta.get_field('mytext').blank = True
Can you please let me know if it works ?
As the discussion goes on I think the correct answer is:
You don't do it on model level. I should do this kind of validation on form level not in a model. Best places are: form fields parameters or form clean method
Is it possible to use self as a reference in the __init__ method when the object is not instantiated yet?
What I'm trying to do is :
class MyClass(models.Model)
__init__(self):
some_attributes = AnotherClass.objects.filter(foreignkey=self)
The thing is that as the instance of MyClass is not registered in db yet, I have an exception like "MyClass has not attribute id"
I tried to add
if self.pk:
but it doesn't work. Is there a method like
if self.is_saved_in_db():
#some code
or do I have to created this one ?
EDIT
To be more specific, I'll give an example. I have a generic class which I try to hydrate with attributes from another Model.
class MyClass(models.Model)
_init__(self):
self.hydrate()
def hydrate(self):
# Retrieving the related objects
attributes = Information.objects.filter(...)
for attr in attributes:
attribute_id = attr.name.lower().replace(" ","_")
setattr(self,attribute_id,attr)
By doing so, I can access to attributes with MyClass.my_attribute.
For a small example, if we replace MyClass by Recipe and Information with Ingredients I can do :
pasta_recipe.pasta
pasta_recipie.tomato
pasta_recipie.onions
It's a simple parsing from a foreign_key to an attribute
By writing it, I realise that it's a bit useless because I can directly use ForeignKey relationships. I think I'll do that but for my own culture, is it possible do the filter with self as attribute before database saving ?
Thanks!
This is a very strange thing to do. I strongly recommend you do not try to do it.
(That said, the self.pk check is the correct one: you need to provide more details than "it doesn't work".)
I'm working on a OpenERP environment, but maybe my issue can be answered from a pure python perspective. What I'm trying to do is define a class whose "_columns" variable can be set from a function that returns the respective dictionary. So basically:
class repos_report(osv.osv):
_name = "repos.report"
_description = "Reposition"
_auto = False
def _get_dyna_cols(self):
ret = {}
cr = self.cr
cr.execute('Select ... From ...')
pass #<- Fill dictionary
return ret
_columns = _get_dyna_cols()
def init(self, cr):
pass #Other stuff here too, but I need to set my _columns before as per openerp
repos_report()
I have tried many ways, but these code reflects my basic need. When I execute my module for installation I get the following error.
TypeError: _get_dyna_cols() takes exactly 1 argument (0 given)
When defining the the _get_dyna_cols function I'm required to have self as first parameter (even before executing). Also, I need a reference to openerp's 'cr' cursor in order to query data to fill my _columns dictionary. So, how can I call this function so that it can be assigned to _columns? What parameter could I pass to this function?
From an OpenERP perspective, I guess I made my need quite clear. So any other approach suggested is also welcome.
From an OpenERP perspective, the right solution depends on what you're actually trying to do, and that's not quite clear from your description.
Usually the _columns definition of a model must be static, since it will be introspected by the ORM and (among other things) will result in the creation of corresponding database columns. You could set the _columns in the __init__ method (not init1) of your model, but that would not make much sense because the result must not change over time, (and it will only get called once when the model registry is initialized anyway).
Now there are a few exceptions to the "static columns" rules:
Function Fields
When you simply want to dynamically handle read/write operations on a virtual column, you can simply use a column of the fields.function type. It needs to emulate one of the other field types, but can do anything it wants with the data dynamically. Typical examples will store the data in other (real) columns after some pre-processing. There are hundreds of example in the official OpenERP modules.
Dynamic columns set
When you are developing a wizard model (a subclass of TransientModel, formerly osv_memory), you don't usually care about the database storage, and simply want to obtain some input from the user and take corresponding actions.
It is not uncommon in that case to need a completely dynamic set of columns, where the number and types of the columns may change every time the model is used. This can be achieved by overriding a few key API methods to simulate dynamic columns`:
fields_view_get is the API method that is called by the clients to obtain the definition of a view (form/tree/...) for the model.
fields_get is included in the result of fields_view_get but may be called separately, and returns a dict with the columns definition of the model.
search, read, write and create are called by the client in order to access and update record data, and should gracefully accept or return values for the columns that were defined in the result of fields_get
By overriding properly these methods, you can completely implement dynamic columns, but you will need to preserve the API behavior, and handle the persistence of the data (if any) yourself, in real static columns or in other models.
There are a few examples of such dynamic columns sets in the official addons, for example in the survey module that needs to simulate survey forms based on the definition of the survey campaign.
1 The init() method is only called when the model's module is installed or updated, in order to setup/update the database backend for this model. It relies on the _columns to do this.
When you write _columns = _get_dyna_cols() in the class body, that function call is made right there, in the class body, as Python is still parsing the class itself. At that point, your _get_dyn_cols method is just a function object in the local (class body) namespace - and it is called.
The error message you get is due to the missing self parameter, which is inserted only when you access your function as a method - but this error message is not what is wrong here: what is wrong is that you are making an imediate function call and expecting an special behavior, like late execution.
The way in Python to achieve what you want - i.e. to have the method called authomatically when the attribute colluns is accessed is to use the "property" built-in.
In this case, do just this: _columns = property(_get_dyna_cols) -
This will create a class attribute named "columns" which through a mechanism called "descriptor protocol" will call the desired method whenever the attribute is accessed from an instance.
To leran more about the property builtin, check the docs: http://docs.python.org/library/functions.html#property
Given a form class (somewhere deep in your giant Django app)..
class ContactForm(forms.Form):
name = ...
surname = ...
And considering you want to add another field to this form without extending or modifying the form class itself, why does not the following approach work?
ContactForm.another_field = forms.CharField(...)
(My first guess is that the metaclass hackery that Django uses applies only the first time the form class is constructed. If so, would there be a way to redeclare the class to overcome this?)
Some pertinent definitions occur in django/forms/forms.py. They are:
class BaseForm
class Form
class DeclarativeFieldsMetaclass
def get_declared_fields
get_declared_fields is called from DeclarativeFieldsMetaclass and constructs a list with the field instances sorted by their creation counter. It then prepends fields from the base classes to this list and returns the result as an OrderedDict instance with the field name serving as the keys. DeclarativeFieldsMetaclass then sticks this value in the attribute base_fields and calls to type to construct the class. It then passes the class to the media_property function in widgets.py and attaches the return value to the media attribute on the new class.
media_property returns a property method that reconstructs the media declarations on every access. My feeling is that it wont be relevant here but I could be wrong.
At any rate, if you are not declaring a Media attribute (and none of the base classes do) then it only returns a fresh Media instance with no arguments to the constructor and I think that monkeypatching a new field on should be as simple as manually inserting the field into base_fields.
ContactForm.another_field = forms.CharField(...)
ContactForm.base_fields['another_field'] = ContactForm.another_field
Each form instance then gets a deepcopy of base_fields that becomes form_instance.fields in the __init__ method of BaseForm. HTH.