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.
Related
I need to get data from different imported MySQL-databases in Django
(Django 1.11.7, Python 3.5.2).
I run manage.py inspectdb --database '<db>' and then use the models in django.
Until now, I only had to access tables with different names. For this purpose, I used the using keyword in the queryset to specify the appropriate database and then concatenated the result, like this:
from ..models.db1 import Members
from ..models.db2 import Actor
context['db1_data'] = Members.objects.using('db1').filter...
context['db2_data'] = Actor.objects.using('db1').filter...
context["member_list"] = list(chain(
context["db1_data"],
context["db2_data"],
))
return context
Now I have the problem that there are tables with the same model names in two databases. I get the following error when using the above-mentioned method (I substituted the names):
RuntimeError: Conflicting '<table-name>' models in application '<app>': <class '<app>.<subfolder>.models.<db1>.<table-name>'> and <class '<app>.<subfolder>.models.<db2>.<table-name>'>.
I already tried importing the model with a different name, like this:
from ..models.db3 import Members as OtherMembers
but the error still comes up.
Shouldn't from ..models.db1 and from ..models.db2 be clear enough for Django to spot the difference between the two models?
One option would probably be to rename the models themselves, but that would mean to rename every database model with the same names. Since I will use many more databases in the future, this is not an option for me.
I tried from models import db1, db2 and then db1.Members etc., which still raises the error.
I read about the meta db_table = 'dbname.tablename'-option, but since the model is auto-generated through inspectdb, it already has something like this on every class:
class MyModel(models.Model):
<models>
class Meta:
managed = False
db_table = 'my_model'
As described before, the other database has the exact same model and hence the same Meta classes. I can't and don't want to change every Meta class.
EDIT:
My project structure looks like this:
app
-> admin.py
-> ...
-> models.py
-> views.py
subfolder
-> models
-> db1.py
-> db2.py
-> views
-> db1.py
-> db2.py
Assuming that you have set up your multiple databases correctly:
Have you tried to add a Custom Router?
If not follow the example given on the documentation link.
Have you tried to use a Custom Manager for your models?
Create a manager for each model, like this:
class YourModelManagerX(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).using('your_db_X')
And then add it to your appropriate model as the objects field:
class YourModel(models.Model):
...
fields
...
objects = YourManagerX()
class Meta:
managed = False
You may need to try both at once.
If db1.Members and db3.Members have the same definition, you do not have to redeclare the Members class separately for each database.
Models.py
...
class Members(models.Model): # Only declared once ever!
....
then,
from Models import Members
context['db1_data'] = Members.objects.using('db1').filter...
context['db3_data'] = Members.objects.using('db3').filter...
... # continue processing
Shouldn't from ..models.db1 and from ..models.db2 be clear enough for django to spot the difference between the two models?
Django Models are not database-specific, more like schema-specific, so if you have the same table in two different databases, one class extending model.Models suffices. Then, when you attempt to retrieve the objects, either specify the database with using(), or using routers, which you can read about in the Django docs https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#an-example
I changed the register logic where now new users have to give their first and second names also. But old users in db don't have those fields filled up, they are empty.
I am wondering now how to set them manually with python manage.py shell, I am using sqlite3, so there is no UI for the db.
is there any solution for it?
the one which came to my mind is to write a update-page for users where they can update their personal info. but then I would need to tell every one of them to do this.
Firstly, I don't know what you mean by "there is no UI for the db" - sqlite has a shell just like any other database, you can go in and write direct SQL update statements.
Secondly, setting fields in the Django shell is just the same as in a view: you import your models, query the instances you want, update the fields, and save the model.
from myapp.models import MyModel
my_instance = MyModel.objects.get(id=whatever)
my_instance.first_name = 'foo'
my_instance.last_name = 'bar'
my_instance.save()
If you are using south, you can do a data migration which is like a schema migration, but deals with data.
You would create a migration, and then add the appropriate code to the forwards method. This way when this migration is applied, data is added for those users that do not have a first and last name.
The other option you have is to do this manually, from the django shell:
>>> from django.contrib.auth import get_user_model
>>> model = get_user_model()
>>> no_names = model.objects.filter(first_name='', last_name='')
>>> no_names.update(first_name='First Name', last_name='Last Name')
After the models.py in one app grew quite large, I've tried to move some of the classes into subpackages.
The old structure was something like this:
# File: assets/models.py
class Asset(...):
# lots of irrelevant code
# File: widgets/models.py
from assets.models import Asset
class Video(...):
asset = models.ForeignKey(Asset)
This worked without a problem, so I'm not going into further details about the structure.
What I've tried to do now is move the Asset class into a submodule. The structure is now as follows:
# File: assets/models/__init__.py (of course I deleted the old models.py)
from .assets import Asset
# File: assets/models/assets.py
class Asset(...):
# lots of irrelevant code
# File: widgets/models.py
from assets.models.assets import Asset
class Video(...):
asset = models.ForeignKey(Asset)
Somehow this doesn't work, and I can't figure out what actually causes the trouble. The error I'm getting is this:
widgets.video: 'asset' has a relation with model , which has either not been installed or
is abstract
It appears that Django can't reliably detect which app a model belongs to if it's in a nested submodule (ie. not directly inside APPNAME.models).
This is a known problem and can be solved by adding the following lines (in this case to the Asset class), thus defining explicitly which app a model belongs to:
class Asset(models.Model):
...
class Meta:
app_label = 'assets'
...
References:
https://groups.google.com/forum/#!topic/django-users/MmaiKvbDlDc
https://code.djangoproject.com/ticket/14007
You should import from models as before:
from assets.models import Asset
This allows you to always import from models but organise the models separately within the models directory. It also means, conceptually, that Asset is still in models as your ForeignKey refers to a assets.models.Asset object, not assets.models.assets.Asset.
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
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.