Getting dynamic collection names in mongoengine - python

Here is the senario. I have a model called Permission. Lets assume it looks like this:
class Permission(Document):
meta = {'collection': 'permission'}
permission = DictField()
owner = ReferenceField('user')
This inherits from the mongoengine's Document class. Thus when I save an instance of this, a collection is automatically created named permission in the database.
I want to be able to change the collection name dynamically. For example if I had a Contacts model and wanted to save the permission for the Contact model I dont want it to go into the permission collection but be saved in a separate collection called contact_permission.
I have used the feature/dynamic_collection_naming branch for mongoengine. I am not able to figure out how to get this working. I have tried this:
p = Permission()
...
p.meta['collection'] = 'contact_permission'
p.save()
But this does not work. Could you help me out please.

That's not the intended API for the dynamic collection naming. Quick search through the commits in the branch you've mentioned shows this commit which shows how to use it:
https://github.com/hmarr/mongoengine/commit/c62b6321adaba6c3eb54ce2dc2c1bd3069568399

Related

Default relation for Django OneToOne Field

I'm trying to create a couple django models with a one to one relation. However I'm trying to get it so the related one to one model is automatically created. If I have something simple like this:
class MyObject(models.Model):
data = models.OneToOneField('MyData', related_name='my_object')
class MyData(models.Model):
info = models.TextField(null=True)
If I create a MyObject and access MyObject.data it will return None. I was hoping there was a way I can have it return a MyData object (just default reference).
I'd like MyObject to automatically have a related MyData object. Is there a way for me to do this or do I need to check every time to see if there's a related MyData object?
Have you seen the official doc?
d = MyData(info='whatever')
o = MyObject(data=d)
How can it be automatic if info text field has to be filled in?
after seeing your edit:
you can probably set my data to be null
o = MyObject(data=Mydata(info=None))
of course, your Mydata should now be able to accept None as their type.

Django Mongodb ListField not saving or updating

I am starting to create a webapp using Django and MongoDB. Everything is working fine when I create a model and save it into the Database. Now, I do a "Class.objects.get()" to get the object I need from my DB and I have one field called "media" which is a ListField(). I had tried doing either:
Concert.media.append(list)
or
Concert.media.extend(list)
and then
Concert.save()
This is my "Concert" object in my models.py:
class Concert(models.Model):
main_artist = models.CharField(max_length=50)
concert_id = models.AutoField(primary_key=True)
openers = ListField(EmbeddedModelField('Opener'))
concert_date = models.DateField()
slug = models.SlugField(unique=True)
media = ListField()
And when I go to see the results in does not update the object. No values where saved. If someone can help me I going to give a super cyber fist bump.
Concert is a class, not an instance. You can't save a class. You need to make an instance of the class and save that. Something like
c = Concert()
c.media.append(list)
c.save()
(btw, just as a note, list is a bad variable name because list is a type in python. Never use types as variable names (though everyone is guilty of this at one point or another, including me.))

Why is save not working in Django?

I'm using manage.py shell and run something like this:
d=Document.objects.get(pk=1)
d.scores
{1:0,2:0,3:0}
d.scores[1]=5
d.scores
{1:5,2:0,3:0}
d.save()
But viewing d in the database reveals that it hasn't been updated. What am I doing wrong?? I checked out what's here, but d is definitely a Document instance.
If it helps, models.py looks like this:
from django.db import models
class Document(models.Model):
fileName=models.CharField(max_length=200)
fileUrl=models.CharField(max_length=200)
scores={1:0,2:0,3:0}
Your 'scores' class variable isn't an instance of any of Django's *Field classes. I would imagine the 'scores' field isn't even on the table in the DB, since the field classes are what defines all of that, and what gets saved to the DB, among other things.

How should I build this Django model to do what I want

This is what I had before (but realized that you can't obviously do it in this order:
class MasterAdmin(models.Model):
"""
A permanent admin (one per Account) that shouldn't be deleted.
"""
admin = models.OneToOneField(AccountAdmin)
class Account(models.Model):
"""
A top-level account in the system.
"""
masteradmin = models.OneToOneField(MasterAdmin)
class AccountAdmin(models.Model):
"""
An Account admin that can be deleted. This includes limited permissions.
"""
account = models.ForeignKey(Account)
I think you can see what I want to do from the example. I want to have an MasterAccountAdmin which shares the attributes from AccountAdmin. The purpose is that I want to give people the ability to delete an AccountAdmin, but not MasterAccountAdmin. I didn't want to just have an attribute on AccountAdmin called "master = models.BooleanField()".
Obviously this example won't work because MasterAdmin is referencing AccountAdmin before its creation, but I wanted to show what I'm trying to achieve. Am I thinking of this all wrong?
Why not just make is_master a property of AccountAdmin and then override the delete() method to ensure is_master is not true?
When you have forward references, use the quotes.
admin = models.OneToOneField('AccountAdmin')
See the docs.
If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself...

Django admin site not displaying ManyToManyField relationship

I'm working on what I think is a pretty standard django site, but am having trouble getting my admin section to display the proper fields.
Here's my models.py:
class Tech(models.Model):
name = models.CharField(max_length = 30)
class Project(models.Model):
title = models.CharField(max_length = 50)
techs = models.ManyToManyField(Tech)
In other words, a Project can have different Tech objects and different tech objects can belong to different Projects (Project X was created with Python and Django, Project Y was C# and SQL Server)
However, the admin site doesn't display any UI for the Tech objects. Here's my admin.py:
class TechInline(admin.TabularInline):
model = Tech
extra = 5
class ProjectAdmin(admin.ModelAdmin):
fields = ['title']
inlines = []
list_display = ('title')
admin.site.register(Project, ProjectAdmin)
I've tried adding the TechInline class to the inlines list, but that causes a
<class 'home.projects.models.Tech'> has no ForeignKey to <class 'home.projects.models.Project'>
Error. Also tried adding techs to the fields list, but that gives a
no such table: projects_project_techs
Error. I verified, and there is no projects_project_techs table, but there is a projects_tech one. Did something perhaps get screwed up in my syncdb?
I am using Sqlite as my database if that helps.
I've tried adding the TechInline class to the inlines list, but that causes a
'TechInLine' not defined
Is that a straight copy-paste? It looks like you just made a typo -- try TechInline instead of TechInLine.
If your syncdb didn't create the proper table, you can do it manually. Execute this command:
python manage.py sqlreset <myapp>
And look for the definition for the projects_project_techs table. Copy and paste it into the client for your database.
Assuming your app is called "projects", the default name for your techs table will be projects_tech and the projects table will be projects_project.
The many-to-many table should be something like projects_project_techs
#John Millikin - Thanks for the sqlreset tip, that put me on the right path. The sqlreset generated code that showed me that the projects_project_techs was never actually created. I ended up just deleting my deb.db database and regenerating it. techs then showed up as it should.
And just as a sidenote, I had to do an admin.site.register(Tech) to be able to create new instances of the class from the Project page too.
I'll probably post another question to see if there is a better way to implement model changes (since I'm pretty sure that is what caused my problem) without wiping the database.

Categories