How to add computed variable to the wagtail StructBlock template context? - python-3.x

I want to compute some custom variable based on the other block values in the StructBlock and add this custom variable to the template context. Essentially I should be able to use this computed variable in the StructBlock template like so {{ value.custom }}.
Here's my StructBlock:
class BaseBlock(blocks.StructBlock):
bool_fld = blocks.BooleanBlock(required=False, default=False)
def get_context(self, *a, **kw):
ctx = super().get_context(*a, **kw)
ctx['custom'] = 1 if self.bool_fld else 0
return ctx
And the error:
'BaseBlock' object has no attribute 'bool_fld'
Any ideas?

The get_context method on block objects receives the block value as its first argument - in the case of StructBlock, this is a dict-like object whose fields can be accessed as value['some_field'].
class BaseBlock(blocks.StructBlock):
bool_fld = blocks.BooleanBlock(required=False, default=False)
def get_context(self, value, parent_context=None):
ctx = super().get_context(value, parent_context=parent_context)
ctx['custom'] = 1 if value['bool_fld'] else 0
return ctx
See also the get_context example at http://docs.wagtail.io/en/v2.0/topics/streamfield.html#template-rendering.
self.bool_fld won't work here, because Block instances do not hold values themselves - they just act as converters between different data representations. (If you've worked with Django form field objects like forms.CharField, blocks are very similar; both block objects and form field objects know how to render values passed to them as form fields, but they don't hold on to those values.)

Related

Python copies/duplicates object rather than instantiates a default one

First off, I'm relatively new to Python, so pardon the rough code I have. Here goes: I have a class with a constructor. It inherits a few properties from a superclass. This same class can also be a child object of itself. So an Epic can hold an Epic, which I'm appending to the Children property as a list.
class Epic(V1Superclass):
Type = 'Epic'
Children = []
ParentAssetID = []
#classmethod
def __init__(self, **kwargs):
for key, value in kwargs.items():
if key == 'Name':
self.Name = value
elif key == 'Description':
self.Description = value
elif key == 'Super':
self.Super = value
elif key == 'Scope':
self.Scope = value
if not bool(self.Super):
self.Super = None
if not bool(self.Scope):
self.Scope = 445082
def populateChildren(self,env,key):
children = V1.utl.getChildren(env,key,'Epic',self.AssetID)
for child in children:
if child['_oid'].split(':')[0] == 'Story':
print('Got another backlog child')
elif child['_oid'].split(':')[0] == 'Defect':
print('Got another Defect child')
elif child['_oid'].split(':')[0] == 'Epic':
childEpic = V1.Epic()
self.Children.append(childEpic)
If I create two instances of this class in the python console, everything's fine. I do "a = V1.Epic()" and "b = V1.Epic()", and the world is good. They all initialize to the proper default values (or empty). However, when I run my code in the populateChildren function, when I instantiate a new Epic object, rather than create a default version of the Epic, it is creating a new instance, but with all the properties of the parent (self) object. In essence, it's an exact copy, but if I do a "self is childEpic" command, it returns false, which (if I understand things correctly) means that childEpic is not a copy of the parent object. I can manipulate the child object and set properties with no problem, but obviously that's not how this should work. This is kind of maddening, as I'm not even sure what to google to see what I'm doing wrong syntax wise.
TIA!
I've tried adding an addChild function which tries to instantiate an instance outside the scope of the parent object, but even within that function, the object created is a duplicate of the parent
Your __init__ function is defined as a class method, which means that its first parameter is not a reference to the instance of the new object, but instead a reference to the current class. These properties are present on each of the class's instances, so it appears that they are being copied over.
Remove the #classmethod decorator from the __init__ function and the self parameter will refer to the object being instantiated.

django-models set record value depends on the existig ones

yo, I have simple Question but it's answer sames to be not ,at all, maybe even not exist !
anyway, I just want to set a django-model field value based on existing ones, LIKE:
class Person(models.Model):
#here is the struggle
people = len(Person.objects.all())
name = medels.Charfield()
#pass it as argument
peopleBeforeYou = models.CharField(default= people-1)
the idea is to set the peopleBeforeYou field default value to that same model QuerySet len()
any idea ????!!!!
You could move the function that counts the number of existing rows to a separate function outside of the class
def count_people():
return Person.objects.count()
class Person(models.Model):
peopleBeforeYou = models.IntegerField(default=count_people)

How to get attributes (not methods) of a class in Python

How to get attributes (not methods) of a class in Python
Hello everyone!
Basically, I'm looking to retrieve all attributes of a class without having access to self (To create a diagram that includes the attributes).
For now I don't have any code, I just have an 'obj' variable which contains the class.
I would therefore like to know, how, via "obj" I can retrieve all the attributes including those which are in functions.
Thanking you in advance,
VitriSnake
You can call __dict__ on your class and it will return a dictionary containing all attributes with their values set by the constructor.
class Tree:
def __init__(self):
self.trunk_size = 20
self.leaf_colour = "Orange"
if "__main__" == __name__:
tree = Tree()
print(tree.__dict__)
Result: {'trunk_size': 20, 'leaf_colour': 'Orange'}
If you just want the values call tree.__dict__.values() and for your keys or rather attribute variable names do tree.__dict__.keys().

Can anyone explain me about __init_ in Python?

List item
class Car:
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.number_of_wheels = 4
self.registration_number = GenerateRegistrationNumber()
Hi all,
1)Referring to the above example, could anyone tell me what is the difference between specific attributed and "the other" attributes? What will happen if registration_number is treated as a specific attribute?
2)
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
If we consider this example, shouldn't it be self.newvalue = newvalue?
I think I know what you're asking (let me know if I'm wrong), but I think you're asking what the difference is between the attributes that are assigned by the parameters of __init__ (Instance Attributes), ones that are assigned inside the __init__ method but not with parameters (also Instance Attributes), and ones that are not assigned in the initialiser at all (Class Attributes). The difference here is that all (well, pretty much all) cars have 4 wheels, and the number plate is generated, not supplied. You could also do this, for example:
class Car:
number_of_wheels = 4
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.registration_number = GenerateRegistrationNumber()
As the number of wheels here is always assigned to the same value, across all instances, it is said to be a "Class Attribute" in this case. All other attributes here are “Instance Attributes” as they are specifically assigned to each instance. For a slightly better explanation, I recommend reading this:
https://www.geeksforgeeks.org/class-instance-attributes-python/
It doesn't actually matter what the instance attribute (self.value here) is called, you could call it whatever you want and it'd still work, but in most cases, you would indeed want to name the attribute the same as the parameter.
init function also called as magic function is a constructor function for a class. if you remember in java whenever we make a class the constructor method should have the same name as the classname but this is not the scenario in python . In python we make use of the init method
the difference between the class attributes and instance attributes is that the class attributes are common to every object that is created but the instance attributes are only accessible by the object that is created.
consider a example where data of students in a class is stored. In such case the class division will be same for all the students of that particular class so it can be common but names of all students are different and also their marks and so on and hence they should be different for everyone
in previous scenario the class division can be class attribute and the data of student like name , marks has to be instance attributes
examples of class attribute is as shown
class A:
Division = 5A
here the division is a class attribute
class B:
def __init__(self,name,marks):
self.name = name
self.marks = marks
here the name and marks are instance variables
now here we can also write self.username = name because we are storing the value of name variable in self.username so you can write any name there is no constraint on that
Also whenever you write __ in front of method or variable it means that the attribute is private and accessible by only class.

Load inconsistent data in pymongo

I am working with pymongo and am wanting to ensure that data saved can be loaded even if additional data elements have been added to the schema.
I have used this for classes that don't need to have the information processed before assigning it to class attributes:
class MyClass(object):
def __init__(self, instance_id):
#set default values
self.database_id = instance_id
self.myvar = 0
#load values from database
self.__load()
def __load(self):
data_dict = Collection.find_one({"_id":self.database_id})
for key, attribute in data_dict.items():
self.__setattr__(key,attribute)
However, in classes that I have to process the data from the database this doesn't work:
class Example(object):
def __init__(self, name):
self.name = name
self.database_id = None
self.member_dict = {}
self.load()
def load(self):
data_dict = Collection.find_one({"name":self.name})
self.database_id = data_dict["_id"]
for element in data_dict["element_list"]:
self.process_element(element)
for member_name, member_info in data_dict["member_class_dict"].items():
self.member_dict[member_name] = MemberClass(member_info)
def process_element(self, element):
print("Do Stuff")
Two example use cases I have are:
1) List of strings the are used to set flags, this is done by calling a function with the string as the argument. (def process_element above)
2) A dictionary of dictionaries which are used to create a list of instances of a class. (MemberClass(member_info) above)
I tried creating properties to handle this but found that __setattr__ doesn't look for properties.
I know I could redefine __setattr__ to look for specific names but it is my understanding that this would slow down all set interactions with the class and I would prefer to avoid that.
I also know I could use a bunch of try/excepts to catch the errors but this would end up making the code very bulky.
I don't mind the load function being slowed down a bit for this but very much want to avoid anything that will slow down the class outside of loading.
So the solution that I came up with is to use the idea of changing the __setattr__ method but instead to handle the exceptions in the load function instead of the __setattr__.
def load(self):
data_dict = Collection.find_one({"name":self.name})
for key, attribute in world_data.items():
if key == "_id":
self.database_id = attribute
elif key == "element_list":
for element in attribute:
self.process_element(element)
elif key == "member_class_dict":
for member_name, member_info in attribute.items():
self.member_dict[member_name] = MemberClass(member_info)
else:
self.__setattr__(key,attribute)
This provides all of the functionality of overriding the __setattr__ method without slowing down any future calls to __setattr__ outside of loading the class.

Resources