3

I am trying create a dynamic function that dynamically add attributes to easily make values accessible in a jinja template.

This code is working but it is static.

# Used to display a cart summary of items that have been pledged.
products_in_cart = Cart.query.filter(Cart.campaign_id == campaign_id).all()
# total_cart_quantity(products_in_cart, "quantity", "quantity_total")
for item in products_in_cart:
    item.quantity_total = 0 #Adding the attribute quantity_total

    for item_loop2 in products_in_cart:
        if item.user_id == item_loop2.user_id:
            item.quantity_total = item.quantity_total + item_loop2.quantity

# Remove duplicate objects based on user_id attribute.
new_set = set()
new_list = []
for obj in products_in_cart:
    if obj.user_id not in new_set:
        new_list.append(obj)
        new_set.add(obj.user_id)

products_in_cart = new_list

I would like to make the added attribute names dynamic based upon arguments passed into the function so I may use elsewhere. Dot notation wont work because I need a variable to name the attribute. obj[variable_attrbute] errors. setattr() does nothing.

def total_cart_quantity(cart_objects, sum_attribute, new_attribute):
'''
    From cart get the total of a particular quantity and add it to a new attribute.
    cart_objects = the queried cart_objects.
    sum_attribute = the attribute to be summed.
    new_attribute = the string of the new attribute name
'''
for item in cart_objects:
    # Two different attempts to add an attribute. 
    # setattr will just not add the attribute
    setattr(item, sum_attribute, new_attribute) # this will do nothing
    # item[new_attribute] = 0 # this will error

    for item_loop2 in cart_objects:
        if item.user_id == item_loop2.user_id:
            item[new_attribute] = item[new_attribute] + item_loop2[sum_attribute]

# Remove duplicate objects based on user_id attribute.
new_set = set()
new_list = []
for obj in cart_objects:
    if obj.user_id not in new_set:
        new_list.append(obj)
        new_set.add(obj.user_id)

products_in_cart = new_list

return products_in_cart

How does one dynamically add attribute names and values?

3
  • Can the answers at stackoverflow.com/questions/4443301/… and stackoverflow.com/questions/2827623/… do what you need? This question has been asked and answered more than a few times already on SO. Commented Jul 24, 2015 at 22:42
  • Why isn't setattr working? Just reading your comments in the code Commented Jul 24, 2015 at 23:43
  • Can use @property decorator to make methods behave like attributes Commented Jul 25, 2015 at 18:40

2 Answers 2

5

You're using getattr and setattr in a wrong way. The actual signatures are following:

variable = object.field  ~  variable = getattr(object, 'field' [, default])
object.field = value     ~  setattr(object, 'field', value)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Alexander, this was the exact issue.
0

You can also use the property decorator to do something like this. For instance:

class CartItem(Base):

   cart_id = Column(ForeignKey("cart.id", primary_key=True)
   item_id = Column(ForeignKey("item.id", primary_key=True)


class Cart(Base):

    id = Column(Integer, primary_key=True)
    items = relationship("CartItems")

    @property
    def number_of_items(self):
       return len(self.items) #or whatever logic you need here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.