I have a models folder that has a few models in files that are already in the DB. I have just added another file/model but it is not being added to the DB when I run syncdb. I've tried manage.py validate and it is running fine. I have also run the code and it only fails when it tries to save with "table does not exist".
the original structure was like this:
/models
-- __init__.py
-- file1.py
-- file2.py
and __init__.py looked like:
from file1 import File1Model
from file2 import File2Model
I added file3.py
/models
-- __init__.py
-- file1.py
-- file2.py
-- file3.py
and modified __init__.py
from file1 import File1Model
from file2 import File2Model
from file3 import File3Model
And the contents of file3 (names may have been changed to protect the innocent, but besides that its the exact file):
UPDATE: just tried adding a primary key since the id field may have been messing with the automatically added integer primary key id. Also tried a few variations but no dice.
from django.db import models
from django.contrib.auth.models import User
class File3Model(models.Model):
user = models.OneToOneField(User)
token = models.CharField(max_length=255, blank=False, null=False)
id = models.CharField(primary_key=True, max_length=255)
class Admin:
pass
class Meta:
app_label = 'coolabel'
def __unicode__(self):
return self.user.username
#staticmethod
def getinstance(user, token, id):
try:
instance = File3Model.objects.get(pk=id)
if instance.token != token:
instance.token = token
instance.save()
return instance
except:
pass
instance = File3Model()
instance.user = user
instance.token = token
instance.id = id
instance.save()
return instance
So in this example, File1Model and File2Model are already in the DB and remain in the DB after syncdb. However, File3Model is not added even after rerunning syncdb. Is there any way to figure out why the new model isn't being added??
If you define the model outside of models.py, you have to set the app_label attribute on the models Meta class.
Edit: The app_label has to refer to an app in your INSTALLED_APPS setting. It should probably match the name of the app that the models directory is in, unless you've got a really good reason to do otherwise. That seems to have been your problem here.
class File3Model(models.Model):
foo = models.CharField(...)
...
class Meta:
app_label = "my_app"
Note that syncdb will never remove any tables from the db. The other tables were probably created with syncdb before the models.py was replaced with the directory structure.
set app_label to my app solves my problem.
Why did you split you models and having models folder instead of placing models in models.py ?
In my own project there are about 10 models live in models.py and I'm fine with it.
You can also try manage.py syncdb --all.
And I think its better to keep all models in one single file and import them like from my_app.models import model_name instead of keeping in mind to import necessary model into models/__init__.py. By the way you avoid many problems and long lined imports and don't care about where some_model lives among models/*.py files.
Thanks,
Sultan
BOOM!
I was using a different app_label for the new model but it has to be the same across the model group.
The other models labels were "mediocrelabel" and my new model had the label "coolabel". I changed the new model's label to "mediocrelabel" and now they are being added to the DB correctly.
Thanks for your help, folks!
Related
I created a custom user model just like the docs said, when I ran the makemigrations I went to the folder of migrations and deleted the first name and last name columns inside the 0001_initial.py and then I ran the migrate command, but when I ran the createsuperuser command it throwed an error in the terminal that django.db.utils.OperationalError: no such column: myapp_usermodel.first_name
How can I fix this?
I want to delete the first name and last name columns because I'm not using them
EDIT: this is the user model
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import AbstractUser
# Create your models here.
class usermodel(AbstractUser):
email = models.EmailField(max_length=60)
username = models.CharField(max_length=20, unique=True)
password = models.CharField(max_length=20)
def __str__(self):
return self.username
I went to the folder of migrations and deleted the first name and last name columns inside the 0001_initial.py
You shouldn't do that. This will indeed prevent Django from creating the columns. But now it will each time query under the impression that the columns are there. Furthermore if you make migrations again, it will try to add extra columns.
You should simply use the method resolution order (MRO) and set the field to None:
class usermodel(AbstractUser):
first_name = None
last_name = None
def __str__(self):
return self.username
You probably also better remove the table in the database and the migration file and make migrations again, and migrate the database.
I have model like this:
class Venue(models.Model):
name = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'venue'
permissions = [
('change_venue', 'Can change venue'),
]
It is not managed because it already exists in the database (which was created before django project).
I want to use django's builtin model permissions, but they are not created by default. I tried to add them by changing Meta.permissions field but got an error: The permission codenamed 'change_venue' clashes with a builtin permission for model 'events.Venue'
What should I do? Just make migration and create permissions manually?
Fixed by creating permissions in App.ready hook:
from django.apps import AppConfig
from django.contrib.auth.management import create_permissions
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
create_permissions(self)
Don't know if this counts as valid solution tho
Edit 1
Method above didn't work for new database because models "were not ready/create" when app is ready. So I switched to post_migrate signal, and everything was fine.
Edit 2
After some time I have found global problem about why I don't have permissions and content types in the first place: I simply didn't make migrations for un-managed models. With migrations everything is fine.
I'm working with an existing django project that uses south. Within each app there's a models folder where models are stored in different files. I have added a new file (shown below) but when I attempt to create migration files for the model, South fails to detect the new file and says: "Nothing seems to have changed." My question is what is the correct way to get south to detect this new model? Thanks.
from django.contrib.auth.models import User, Group
from django.db import models
from django.contrib import admin
class AdgroupEmailRecipients(models.model):
users = models.ForeignKey(User)
class Meta:
app_label = 'wifipromo'
class AdgroupEmailRecipientsAdmin(admin.ModelAdmin):
list_display = ('user_first_name', 'user_last_name', 'user_email')
def user_first_name(self, obj):
return obj.users.first_name
user_first_name.short_description = "First Name"
def user_last_name(self, obj):
return obj.users.last_name
user_last_name.short_description = "Last Name"
def user_email(self, obj):
return obj.users.email
user_email.short_description = "Email"
In the __init__.py file of the models folder, you have to import the model for South or even syncdb to detect it. Basically django is just looking for one file with all your models... and if you import it all in init.py that's what the system will see.
So I successfully migrated from a profile model to an extended User model. The data migration all worked fine, but I can't access my users from the admin, I get the following error:
DatabaseError: (1146, "Table 'mydb.app_myuser_groups' doesn't exist")
All I have defined in models.py is the following:
class MyUser(AbstractUser):
isSpecial = models.BooleanField(default=True)
having followed these instructions. Is there more I need to do to get this to work?
See my previous answer here and modify step 4 to look like this:
# encoding: utf-8
from south.db import db
from south.v2 import SchemaMigration
class Migration(SchemaMigration):
def forwards(self, orm):
# Fill in the destination name with the table name of your model
db.rename_table('auth_user', 'accounts_user')
db.rename_table('auth_user_groups', 'accounts_user_groups')
def backwards(self, orm):
db.rename_table('accounts_user', 'auth_user')
db.rename_table('accounts_user_groups', 'auth_user_groups')
models = { ....... } # Leave this alone
AbstractUser inherits from PermissionMixin, which has a ManyToManyField to the Group model. So there should be a app_myuser_groups table in the database. South may be able to create the intermediate table, but I don't know how. What I know is that syncdbing after having removed app_myuser should work, even though your migration would be shredded.
This question about adding a through table in a migration should give you more insight.
In order to place my models in sub-folders I tried to use the app_label Meta field as described here.
My directory structure looks like this:
project
apps
foo
models
__init__.py
bar_model.py
In bar_model.py I define my Model like this:
from django.db import models
class SomeModel(models.Model):
field = models.TextField()
class Meta:
app_label = "foo"
I can successfully import the model like so:
from apps.foo.models.bar_model import SomeModel
However, running:
./manage.py syncdb
does not create the table for the model. In verbose mode I do see, however, that the app "foo" is properly recognized (it's in INSTALLED_APPS in settings.py). Moving the model to models.py under foo does work.
Is there some specific convention not documented with app_label or with the whole mechanism that prevents this model structure from being recognized by syncdb?
See Django ticket #10985: Explain how models can be organised in a directory
It may be that you aren't importing your models into __init__.py?
syncdb will not create tables for models not located in <appname>.models, so import it in there, e.g. from apps.foo.models import SomeModel.
Here is a solution if you have a newer version of Django, supposing you have a subfolder named subfolder :
in apps.py of your folder app:
from django.apps import AppConfig
class MyappConfig(AppConfig):
name = 'myapp'
def ready(self):
from myapp.subfolder import models