I have two classes defined like so in my models.py file:
class Branch_Circle(models.Model):
...
trunk_circle = models.ForeignKey('Trunk_Circle', null=True)
class Trunk_Circle(models.Model):
...
def create_branch_circle(self):
branch_circle = Branch_Circle(trunk_circle=self)
branch_circle.save()
return branch_circle
Using shell I instantiate a Trunk_Circle object first, then call its 'create_branch_circle' method and expect it to create a Branch_Circle object. It doesn't:
import Trunk_Circle
import Branch_Circle
r = Trunk_Circle
s = r.create_branch_circle
When I call Branch_Circle.objects.all() it is empty. Also, the type of 's' is <bound method Trunk_Circle.create_branch_circle of <Trunk_Circle: Trunk_Circle object>>
To instantiate an object or call a method you have to use brackets ():
r = Trunk_Circle()
s = r.create_branch_circle()
Related
I need to convert some code from python 3 to python 2. I have a metaclass where the __prepare__ method sets up a function in the class dict. I tried to translate to a __new__ method but I am unable to set up the SET_DEFAULTS function. Is that possible ?
I have a NameError: name 'SET_DEFAULTS' at initialization
class UazeMessageMeta (type):
#staticmethod
def __prepare__(name, bases, **kwargs):
d = {}
for b in bases:
if 'DEFAULT_VALUES' in dir(b):
d.update(b.DEFAULT_VALUES)
return {
'SET_DEFAULTS' : lambda **kwargs : d.update(kwargs),
'DEFAULT_VALUES' : d
}
class UazeMessage (bytearray):
"""
A basic message (header only). This class also provides the
base behavior for all messages.
"""
# gp test py27 -----------------
__metaclass__ = UazeMessageMeta
# ------------
priority = MessageField(0, 1, Priority)
sequence = MessageField(1, 7, FieldType.UNSIGNED)
readWrite = MessageField(8, 1, ReadWriteFlag)
ack = MessageField(9, 2, Ack)
channel = MessageField(11, 2, FieldType.UNSIGNED)
category = MessageField(13, 3, Category)
item = MessageField(16, 8, FieldType.UNSIGNED)
DEFAULT_SIZE = 3
def __init__(self, init=0, setdefaults=None, **kwargs):
# If init is still or None, initialize the size of the message
# using the default size provided in the class.
if init == None or init == 0:
init = type(self).DEFAULT_SIZE
super(UrmpMessage,self).__init__(init)
# Set any default or provided fields.
initval = {}
if (isinstance(init, int) and setdefaults != False) or \
(setdefaults == True):
initval = dict(self.DEFAULT_VALUES)
initval.update(kwargs)
for key, value in initval.items():
setattr(self, key, value)
class ResetBase (UazeMessage):
"""Reset response/request structure."""
resetType = MessageField(24, 8, ResetType)
SET_DEFAULTS(
category = Category.OPERATION,
resetType = ResetType.SOFT,
item = 0)
DEFAULT_SIZE = 4
Ordinarily, you can't do that.
The introduction of __prepare__ is a fundamental change in Python3, which allows the customization of the namespace where a class body itself is parsed.
I believe the main motivation doing that was to provide a way to replace the local namespace inside a class body with an OrderedDict, so that the class initialization (in the metaclass __new__ or __init__ methods) could benefit from the declaration order of methods and attributes inside the class body. It should be considered that as of Python 3.6 (final version due this week), an ordered dictionary is used by default in the class body, and a metaclass is no longer necessary for that.
The __prepare__ mechanism is way more flexible than that, and in a simpler use, allow one to simply pre-populate the class body dictionary with predetermined values. That is what your project do.
However, since this code does not need an special dictionary class, and just pre-populate an ordinary dictionary, all you need to do is to write an ordinary function that takes in a dictionary and base classes as parameters, and fills in that dictionary according to the existing code in the __prepare__ method. Then, call that function in the beggining of a class body, passing in the dictionary returned by the locals() call as parameter. That is it: the class body namespace can be pre-filled in the sameway.
def prepare(bases, dct):
for base in bases:
dct["special_attribute"] = {}
if "special_attribute" in base.__dict__:
dct["special_attribute" ].update(base.__dict__["special_attribute"])
...
class MyClass(bytearray):
prepare((bytearray,), locals())
...
All that said, I really advise you to try if possible NOT to backport a project to Python2 at this point in time - it will just complicate your codebase - and give up using new features in a consistent way (for example, this tip above instead of __prepare__ )
Could someone translate this Java Pseudo code with generics to Django models? I don't understand the content type concept. It would also be possible to leave out the map and just have a list of KeyValuePairs or KeyValueExamples.
class Dictionary<T extends KeyValuePair>
class KeyValuePair
String key
String value
class KeyValueExample extends KeyValuePair
String example
class Container
Dictionary<KeyValuePair> itemsOne
Dictionary<KeyValueExample> itemsTwo
Django's contenttypes doesn't have anything common with generics from Java. Python has a dynamic type system so there is no need for generics.
This means that you can put any object of any class into the dictionary:
class Container(object):
def __init__(self):
self.itemsOne = {}
self.itemsTwo = {}
container = Container()
container.itemsOne['123'] = '123'
container.itemsOne[321] = 321
container.itemsTwo[(1,2,3)] = "tuple can be a key"
If you want to implement your classes in django models then code could be something like this:
class KeyValuePairBase(models.Model):
key = models.CharField(max_length=30)
value = models.CharField(max_length=30)
class Meta:
abstract = True
class KeyValuePair(KeyValuePairBase):
pass
class KeyValueExample(KeyValuePairBase):
example = models.CharField(max_length=30)
class Container(models.Model):
items_one = models.ManyToManyField(KeyValuePair)
items_two = models.ManyToManyField(KeyValueExample)
# usage of these models
kvp = KeyValuePair.objects.create(key='key', value='value')
kve = KeyValueExample.objects.create(key='key', value='value',
example='Example text')
container = Container.objects.create()
container.items_one.add(kvp)
container.items_two.add(kve)
I am trying to use google's ndb model, adding some auto fields and definitions prior to model definition. The below code works well. My question is, though, any specific ndb model implementation is not used ( given I will be destroyed, if google changes anything) do you see any issue with portability of below
class MetaModel(type):
def __new__(cls,name,bases,attrs):
super_new = super(MetaModel,cls).__new__
if name == "Model":
return super_new(cls,name,bases,attrs)
if attrs.get('auto_date_time',True):
attrs['date_add'] = ndb.DateTimeProperty(auto_now_add= True)
attrs['date_upd'] = ndb.DateTimeProperty(auto_now= True)
attrs['_get_kind'] = classmethod(get_kind)
attrs['__name__'] = name
attr_meta = attrs.get('Meta',None)
if attr_meta is None:
meta = type('meta',(object,),dict())
else:
meta = attr_meta
kwargs= {}
model_module = sys.modules[attrs['__module__']]
kwargs['app_label'] = model_module.__name__.split('.')[-2]
_meta = Options(meta,name,**kwargs)
attrs['_meta'] = _meta
return type(name,(ndb.Model,),attrs)
class Model(object):
__metaclass__ = MetaModel
class TesTModel(Model):
name = ndb.StringProperty(indexed=False)
tm = TestModel(name='This is the test model')
tm.put()
This seems pretty fragile. Sounds like an expando model might work for you?
Edit (based on clarification below): metaclasses and type really should be a last resort. They're confusing and hard to get right. For example, in your code snippet, subclasses of Model get ndb's metaclass instead of the one above:
class T1(Model):
pass
>>> T1().to_dict()
T1 {'date_upd': None, 'date_add': None}
class T2(Model):
auto_date_time = False
class T3(T2):
auto_date_time = True
>>> T2.__metaclass__
<class 'ndb.model.MetaModel'>
>>> T3().to_dict()
{}
You can avoid some craziness by deriving your metaclass from ndb.MetaModel:
class MyMetaModel(ndb.MetaModel):
def __new__(cls, name, bases, attrs):
return super(MyMetaModel,cls).__new__(cls, name, bases, attrs)
class MyModel(ndb.Model):
__metaclass__ = MyMetaModel
class AutoTimeModel(MyModel):
date_add = ndb.DateTimeProperty(auto_now_add=True)
date_upd = ndb.DateTimeProperty(auto_now=True)
since four days I'm trying to figure out how to follow a reference from one to another class, starting from the class which is beeing referenced. In SQL-Django there is a related_name to achieve this...
For example I have this class:
class MyClass(Document):
...
other_classes = ListField(ReferenceField(Other_Class))
and this one:
class Other_Class(Document):
...
Now I want to go from Other_Class to MyClass... Any ideas?
Thanks,
Ron
Here is a test case showing how to query it:
import unittest
from mongoengine import *
class StackOverFlowTest(unittest.TestCase):
def setUp(self):
conn = connect(db='mongoenginetest')
def test_one_two_many(self):
class MyClass(Document):
other_classes = ListField(ReferenceField("OtherClass"))
class OtherClass(Document):
text = StringField()
MyClass.drop_collection()
OtherClass.drop_collection()
o1 = OtherClass(text='one').save()
o2 = OtherClass(text='two').save()
m = MyClass(other_classes=[o1, o2]).save()
# Lookup MyClass that has o1 in its other_classes
self.assertEqual(m, MyClass.objects.get(other_classes=o1))
# Lookup MyClass where either o1 or o2 matches
self.assertEqual(m, MyClass.objects.get(other_classes__in=[o1, o2]))
The main question is do you need to store a list of references in the MyClass? It might be more efficient to store the relationship just on OtherClass..
Try this query:
oc = Other_Class()
MyClass.objects.find( other_classes__all = [oc.id] )
While thinking about my problem I came up with a solution.
I just add the ID of my referenced class to my model.
Here's an example:
class MyClass(Document):
...
other_classes = ListField(ReferenceField(Other_Class))
class Other_Class(Document):
myclass = ReferenceField(MyClass)
I'm not quite sure if this is the Mongo-way to do it but I'm pretty sure it works :)
Optionally you can omit the other_classes attribute in MyClass to avoid redundancy but then you need a query like this to get the "child" objects:
Other_Class.objects(myclass = myclass.id)
I have two models:
class ModelOne(models.Model):
something = models.TextField[...]
class ModelTwo(models.Model):
other_something = models.TextField[...]
ref = models.ForeignKey(ModelOne)
And I want to write function in ModelOne which return me all related objects from ModelTwo.
It's important: In ModelOne.
How to do it?
Invoke self.modeltwo_set.all().