python can't set attribute on non-persistent property

  • Last Update :
  • Techknowledgy :

You need to define a setter function for your property too, right now, it is read-only (see, e.g., this question).

class class User(models.Model):
   email = models.EmailField(max_length = 254, unique = True, db_index = True)

def client_id(self):
   return self.internal_client_id

def client_id(self, value):
   self.internal_client_id = value

Suggestion : 2

In this example, Book objects have an authors object that’s a regular Python list, so it’s mutable and non-persistent. When we add an author, we append it to the authors attribute’s value. Because we didn’t set an attribute on the book, it’s not marked as changed, so we set _p_changed ourselves.,Note that in this example, when we added an author, the book itself didn’t change, but the authors attribute value did. Because authors is a persistent object, it’s stored in a separate database record from the book record and is managed by ZODB independent of the management of the book.,When implementing persistent objects, be aware that an object’s attributes should be :,While you can do anything with a persistent subclass that you can with a normal subclass, certain things have additional implications for persistent objects. These often show up as performance issues, or the result may become hard to maintain.

import persistent

class Book(persistent.Persistent):

   def __init__(self, title):
   self.title = title
self.authors = []

def add_author(self, author):
self._p_changed = True
import persistent

class Book(persistent.Persistent):

   def __init__(self, title):
   self.title = title
self.authors = ()

def add_author(self, author):
   self.authors += (author, )
import persistent
import persistent.list

class Book(persistent.Persistent):

   def __init__(self, title):
   self.title = title
self.authors = persistent.list.PersistentList()

def add_author(self, author):
import persistent
from BTrees.OOBTree
import TreeSet

class Book(persistent.Persistent):

   def __init__(self, title):
   self.title = title
self.authors = TreeSet()

def add_author(self, author):
class Book(persistent.Persistent):

   publisher = 'UNKNOWN'

def __init__(self, title, publisher):
   self.title = title
self.publisher = publisher
self.authors = TreeSet()

def add_author(self, author):
from catalog
import Publication as Book # XXX deprecated name

Suggestion : 3

Attributes allow you to to store arbitrary data on objects and make sure the data survives a server reboot. An Attribute can store pretty much any Python data structure and data type, like numbers, strings, lists, dicts etc. You can also store (references to) database objects like characters and rooms.,add(...) - this adds a new Attribute to the object. An optional lockstring can be supplied here to restrict future access and also the call itself may be checked against locks.,NAttributes can store any Python structure (and database object) without limit.,NAttributes (short of Non-database Attributes) mimic Attributes in most things except they are non-persistent - they will not survive a server reload.

> set obj / myattr = "test" = [1, 2, 3, "bar"]
value =
obj.attributes.add("myattr", 1234, category = "bar")
value = attributes.get("myattr", category = "bar")
from evennia
import DefaultObject
from evennia
import AttributeProperty

class MyObject(DefaultObject):
   foo = AttributeProperty(
      default = [1, 2, 3, "bar"])
myattr = AttributeProperty(100, category = 'bar')
import evennia

obj = evennia.create_object(key = "Foo")

obj.db.foo1 = 1234
obj.db.foo2 = [1, 2, 3, 4]
obj.db.weapon = "sword"
obj.db.self_reference = obj # stores a reference to the obj

#(let 's assume a rose exists in-game)
      rose = evennia.search_object(key = "rose")[0] # returns a list, grab 0 th element rose.db.has_thorns = True

      # retrieving val1 = obj.db.foo1 val2 = obj.db.foo2 weap = obj.db.weapon myself = obj.db.self_reference # retrieve reference from db, get object back

      is_ouch = rose.db.has_thorns

      # this will
      return None, not AttributeError!
         not_found = obj.db.jiwjpowiwwerw

      # returns all Attributes on the object obj.db.all

      # delete an Attribute del obj.db.foo2
is_ouch = rose.attributes.get("has_thorns")

obj.attributes.add("helmet", "Knight's helmet")
helmet = obj.attributes.get("helmet")

# you can give space - separated Attribute - names(can 't do that with .db)
      obj.attributes.add("my game log", "long text about ...")

Suggestion : 4

Properties: attributes defined by get/set methods ,Properties are a neat way to implement attributes whose usage resembles attribute access, but whose implementation uses method calls. These are sometimes known as "managed attributes". In prior Python versions, you could only do this by overriding __getattr__ and __setattr__; but overriding __setattr__ slows down all attribute assignments considerably, and overriding __getattr__ is always a bit tricky to get right. Properties let you do this painlessly, without having to override __getattr__ or __setattr__. ,A note about __setattr__: sometimes attributes are not stored in self.__dict__ (for example when using __slots__ or properties, or when using a built-in base class). The same pattern as for __getattribute__ applies, where you call the base class __setattr__ to do the actual work. Here's an example: ,Why will this be a problem in the new system? The 'object' type at the top of the type hierarchy defines a number of methods that can usefully be extended by subtypes, for example __getattribute__() and __setattr__().

Any algorithm for deciding the method resolution order may be confronted with contradicting requirements. This shows up for example when two given base classes occur in a different order in the inheritance list of two different derived classes, and those derived classes are both inherited by yet another class. Here's an example:

class A(object):
   def meth(self): return "A"
class B(object):
   def meth(self): return "B"

class X(A, B): pass
class Y(B, A): pass

class Z(X, Y): pass
class A:
   def foo(self): pass

class B(A): pass

class C(A):
   def foo(self):

Suggestion : 5

If you are using Python property mutator and even if it does not write to the object it still will trigger the object rewrite.,When Persitent object is modified, via attribute set or __setattr__() call, the current transaction is converted to a write transaction. Write transactions are usually undoable (visible on Zope’s Undo tab).,If you modify objects inside persistent lists and dictionaries, the change is not automatically reflected to the parent container.,Volatiles are useful when framework expects the object to conform certain interface, like form frameworks. However, your persistent object edited by form cannot have persistent attributes for all variables the form expects to see.

from persistent
import Persistent
from zope.annotation
import IAnnotations

class VolatileContext(object):
" Mix-in class to provide context variable to persistent classes which is not persistent.

Some subsystems(e.g.forms) expect objects to have a reference to parent / site / whatever.
However, it might not be a wise idea to have circular persistent references.

This helper class creates a context property which is volatile(never persistent),
   but can be still set on the object after creation or after database load.

def _set_context(self, context):
   self._v_context = context

def _get_context(self):
   return self._v_context

class MobileBehaviorStorage(VolatileContext, Persistent):
"Set mobile specific field properties on the context object and return the context object itself.#

This allows to use attribute storage with schema input validation.

mobileFolderListing = FieldPropertyDelegate(IMobileBehavior["mobileFolderListing"])

KEY = "mobile"

def manufacture_mobile_behavior(context):

   annotations = IAnnotations(context)
if not KEY in annotations:
   annotations[KEY] = MobileBehaviorStorage()

object = annotations[KEY]

# Set volatile context
object.context = context

return object
if hasattr(self, '_v_image'):
   return self._v_image
marker = []
value = getattr(self, "_v_image", marker)
if value is not marker:
   return value
return self._v_image
except AttributeError:
self._v_image = expensive_calculation()
return self._v_image

Suggestion : 6

Don’t override request.session with a new object, and don’t access or set its attributes. Use it like a Python dictionary.,When SessionMiddleware is activated, each HttpRequest object – the first argument to any Django view function – will have a session attribute, which is a dictionary-like object.,If value is an integer, the session will expire after that many seconds of inactivity. For example, calling request.session.set_expiry(300) would make the session expire in 5 minutes.,Use normal Python strings as dictionary keys on request.session. This is more of a convention than a hard-and-fast rule.

expires_at = modification + timedelta(seconds = settings.SESSION_COOKIE_AGE)
>>> # initial assignment
   request.session[0] = 'bar' >>>
   # subsequent requests following serialization & deserialization >>>
   # of session data >>>
   request.session[0] # KeyError >>>
def post_comment(request, new_comment):
   if request.session.get('has_commented', False):
   return HttpResponse("You've already commented.")
c = comments.Comment(comment = new_comment)
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')
def login(request):
   m = Member.objects.get(username = request.POST['username'])
if m.check_password(request.POST['password']):
   request.session['member_id'] =
return HttpResponse("You're logged in.")
   return HttpResponse("Your username and password didn't match.")
def logout(request):
   del request.session['member_id']
except KeyError:
return HttpResponse("You're logged out.")
from django.http
import HttpResponse
from django.shortcuts
import render

def login(request):
   if request.method == 'POST':
   if request.session.test_cookie_worked():
return HttpResponse("You're logged in.")
   return HttpResponse("Please enable cookies and try again.")
return render(request, 'foo/login_form.html')