I'm using django-mongodb-engine to make a site.
I have a custom user model that looks like this:
class User(AbstractUser):
trigrama = models.CharField(max_length=3, unique=True)
external_email = models.EmailField(unique=True)
phone_number = models.CharField(max_length=20, unique=True)
AbstractUser._meta.get_field_by_name('email')[0]._unique=True
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [
'first_name', 'last_name', 'trigrama',
'external_email', 'phone_number', 'username'
]
It works just fine, but then I tried adding an embedded document to the user model:
permissions = EmbeddedModelField('Permission')
Permission
is a class that looks like this:
class Permission(models.Model):
computers = ListField(EmbeddedModelField('Computer'))
projects = ListField(EmbeddedModelField('Project'))
scripts = ListField(EmbeddedModelField('Script'))
Now when I try to crate a user in the shell using User.objects.create()
I get the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 149, in create
return self.get_query_set().create(**kwargs)
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 416, in create
obj.save(force_insert=True, using=self.db)
File "C:\Python27\lib\site-packages\django\db\models\base.py", line 548, in save
force_update=force_update, update_fields=update_fields)
File "C:\Python27\lib\site-packages\django\db\models\base.py", line 668, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 215, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1675, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "C:\Python27\lib\site-packages\djangotoolbox\db\basecompiler.py", line 583, in execute_sql
"field) to None!" % field.name)
IntegrityError: You can't set permissions (a non-nullable field) to None!
I tried setting the default to Permission()
using:
permissions = EmbeddedModelField('Permission', default=Permission())
but then I get the following error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 149, in create
return self.get_query_set().create(**kwargs)
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 416, in create
obj.save(force_insert=True, using=self.db)
File "C:\Python27\lib\site-packages\django\db\models\base.py", line 548, in save
force_update=force_update, update_fields=update_fields)
File "C:\Python27\lib\site-packages\django\db\models\base.py", line 668, in save_base
result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
File "C:\Python27\lib\site-packages\django\db\models\manager.py", line 215, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "C:\Python27\lib\site-packages\django\db\models\query.py", line 1675, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "C:\Python27\lib\site-packages\djangotoolbox\db\basecompiler.py", line 579, in execute_sql
connection=self.connection
File "C:\Python27\lib\site-packages\djangotoolbox\fields.py", line 364, in get_db_prep_save
(embedded_model, type(embedded_instance)))
TypeError: Expected instance of type <class 'users.models.Permission'>, not <type 'unicode'>.
So how should I go about adding an embedded document to the custom user model?
P.S.
If I type Permission()
in the shell it instantiates just fine, returning a Permission object
and not a unicode.
If you read the docs about the way to set a default value for a field, you'll see that it expects to recieve a value... or a callable object. You can't just create the instance then and there, it doesn't work like that (emphasis mine):
The default cannot be a mutable object (model instance, list, set, etc.), as a reference to the same instance of that object would be used as the default value in all new model instances.
When you call it yourself (i.e. Permission()
) what you get is an instance, which, in turn, returns a unicode (it's calling the __unicode__
function).
In other words, just drop the trailing ()
:
permissions = EmbeddedModelField('Permission', default=Permission)
Now, in truthfulness, this might be problematic, because it doesn't actually saves that new permission object, and the whole thing can become messy (this being permissions and all, you want to be extra careful). So it might be better to create a function to wrap the operation, and use that instead:
def get_initial_perms():
p = Permission()
p.save()
return p
# later:
permissions = EmbeddedModelField('Permission', default=get_initial_perms)
A similar solution would be to override the save()
method and give the object a permission before calling the acutal save
part.