I have two users, mh00h1 and mh00h2. I also have modelA that defines the following in my models.py:
class Meta:
permissions = (
('read','read'),
('write','write'),
)
From a shell, I went to set permissions:
>>>> frhde = create modelA instance
>>>> assign_perm('read', mh00h2, frhde)
DoesNotExist: Permission matching query does not exist. Lookup parameters were {'codename': u'read', 'content_type': <ContentType: modelA>}
I realized that South didn't migrate my models after I added class Meta to modelA and confirmed this. Changing read to read2 shows that South does not detect the change.
$ /manage.py schemamigration myapp --auto
Running migrations for myapp:
- Nothing to migrate.
- Loading initial data for myapp.
Installed 0 object(s) from 0 fixture(s)
Running migrations for guardian:
- Nothing to migrate.
- Loading initial data for guardian.
Installed 0 object(s) from 0 fixture(s)
How can I get schematicmigration to correctly update the database, or is there a better way to do this that does not require redoing the whole database?
Thank you.
You can use ./manage.py syncdb --all, or create a signal like in this post.
Related
I need one help. I have one existing mysql table in my localhost database and I need it to migrate using Django and Python. Here is my code:
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djangotest',
'USER': 'root',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
I am giving my table structure below.
Person:
id name phone age
models.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=200)
phone = models.CharField(max_length=15)
age = models.IntegerField()
Actually I am new to Django and Python and here I need to know command which can migrate the existing table.
to create migrations you need to use this command -
python manage.py makemigrations
the above command will create a file inside the migrations folder in your app directory and
to create/update table using the migration file in the database
python manage.py migrate
The above command will create/update a table in your DB.
Django Migration Docmentation
Let me know, if this is what you want!
In reference to akhilsp, I did not have to worry about table names using the _ format. Using the inspectdb command returned a Meta data for whatever the current table name is that I used in my model.
class Meta:
managed = False
db_table = 'malware'
Add --fake option to migrate command:
--fake
Tells Django to mark the migrations as having been applied or unapplied, but without actually running the SQL to change your
database schema.
This is intended for advanced users to manipulate the current
migration state directly if they’re manually applying changes; be
warned that using --fake runs the risk of putting the migration state
table into a state where manual recovery will be needed to make
migrations run correctly.
If you just start django project and didn't have initial migration: comment your Person model, make initial migration, apply it, uncomment Person, make migration for Person and at last migrate Person with --fake option.
You can use inspectdb command from the shell.
python manage.py inspectdb
This will print models corresponding to the current database structure. You copy the required model, make changes like adding validations, and then add other models.
python manage.py makemigrations will create migrations, and
python manage.py migrate will apply those migrations.
N.B: Your table name should be in the format "appname_modelname" where appname is name for django app name (not project name).
I have 2 models - Facility and Slot.
class Facility(BaseModel):
name = models.CharField()...
class Slot(BaseModel):
name = models.CharField()...
slot = models.ForeignKey(Facility)
These work perfectly fine.
Now I am adding another model:-
class BlockedSlot(BaseModel):
slots = models.ManyToManyField(Slot)
Now when I run python manage.py makemigrations, it successfully creates a migration file.
But when I run python manage.py migrate, it gives the error - relation "facilities_slot" does not exist.
(models are in facilities.py)
I even tried resetting the db and trying, but it still fails.
I even deleted all the existing migrations and reran makemigrations that generated the 0001_initial.py and again ran migrate, but still fails.
I need to change the relationship of a model field from ForeignKey to ManyToManyField. This comes with a data migration, to update the pre-existing data.
The following is the original model (models.py):
class DealBase(models.Model):
[...]
categoria = models.ForeignKey('Categoria')
[...]
)
I need the model field 'categoria' to establish a many2many relationship with the model 'Categoria' in the app 'deal'.
What I did:
Create a new field 'categoria_tmp' in DealBase
class DealBase(models.Model):
categoria = models.ForeignKey('Categoria')
categoria_tmp = models.ManyToManyField('Categoria',related_name='categoria-temp')
make a schema migration
python manage.py makemigrations
Edit the migrationfile.py to migrate data from categoria to categoria-tmp
def copy_deal_to_dealtmp(apps, schema_editor):
DealBase = apps.get_model('deal', 'DealBase')
for deal in DealBase.objects.all():
deal.categoria_tmp.add(deal.categoria)
deal.save()
class Migration(migrations.Migration):
dependencies = [
('deal', '0017_dealbase_indirizzo'),
]
operations = [
migrations.AddField(
model_name='dealbase',
name='categoria_tmp',
field=models.ManyToManyField(related_name='categoria-temp', to='deal.Categoria'),
preserve_default=True,
),
migrations.RunPython(
copy_deal_to_dealtmp
)
]
make data migration
python manage.py migrate
Finally I need to delete the column 'dealbase.categoria' and rename the column 'dealbase.categoria-tmp' to 'dealbase.categoria'
I'm stuck at step 5.
Could someone help me out? I cannot find online an answer, I'm using Django 1.8.
Thanks!
You just need to create two additional migrations: one to remove the old field and the other to alter the new field.
First remove dealbase.categoria and create a migration and then rename dealbase.categoria-tmp to dealbase.categoria and create another migration.
This will delete the first field and then alter the tmp field to the correct name.
Try this, may help you.
Step 1 as yours
python manage.py makemigrations && python manage.py migrate
Open shell
for i in DealBase.objects.all()
i.categoria_tmp.add(i.categoria)
Remove your field categoria
python manage.py makemigrations && python manage.py migrate
Add field
categoria = models.ManyToManyField('Categoria',related_name='categoria-temp')
Then
python manage.py makemigrations && python manage.py migrate
Open shell
for i in DealBase.objects.all():
for j in i.categoria_tmp.all():
i.categoria.add(j)
Remove field categoria_tmp
python manage.py makemigrations && python manage.py migrate
If you don't have any data in this model, just comment on that model, and then run manage.py makemigrations and migrate. Then delete the wrong field and delete the comment code, and make makemigrations and migrate. This also works in Django 2.
I want share with you this case:
I have the models Albums, Artists, and Tracks
One Artist may have many Albums
One Album may have many Tracks
Many Tracks are inside One Album (may be ManyToMany too ..)
In the Albums Model I want add a field of type SlugField. This is the following:
from django.db import models
from artists.models import Artists
class Album(models.Model):
title = models.CharField(max_length=255)
cover = models.ImageField(upload_to='albums')
slug = models.SlugField(max_length=100)
artist = models.ForeignKey(Artists)
def __unicode__(self):
return self.title
I perform the migratios with south:
(myvenv)➜ myvenv ./manage.py syncdb
Syncing...
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
Synced:
> django.contrib.admin
> django.contrib.auth
> django.contrib.contenttypes
> django.contrib.sessions
> django.contrib.messages
> django.contrib.staticfiles
> south
> albums
Not synced (use migrations):
- django_extensions
- djcelery
- tracks
- artists
- userprofiles
(use ./manage.py migrate to migrate these)
(myenv)➜ myenv ./manage.py convert_to_south albums
Creating migrations directory at '/home/bgarcial/workspace/myenv/sfotipy/albums/migrations'...
Creating __init__.py in '/home/bgarcial/workspace/myenv/sfotipy/albums/migrations'...
+ Added model albums.Album
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate albums
- Soft matched migration 0001 to 0001_initial.
Running migrations for albums:
- Nothing to migrate.
- Loading initial data for albums.
Installed 0 object(s) from 0 fixture(s)
App 'albums' converted. Note that South assumed the application's models matched the database
(i.e. you haven't changed it since last syncdb); if you have, you should delete the albums/migrations directory, revert models.py so it matches the database, and try again.
(myenv)➜ myenv ./manage.py migrate albums
Running migrations for albums:
- Nothing to migrate.
- Loading initial data for albums.
Installed 0 object(s) from 0 fixture(s)
If I enter the command ./manage.py sqlall, the albums model already appear with the slug field at database
(Sfoti.py)➜ sfotipy ./manage.py sqlall albums
BEGIN;
CREATE TABLE "albums_album" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(255) NOT NULL,
"cover" varchar(100) NOT NULL,
"slug" varchar(100) NOT NULL,
"artist_id" integer NOT NULL REFERENCES "artists_artists" ("id")
);
CREATE INDEX "albums_album_f52cfca0" ON "albums_album" ("slug");
CREATE INDEX "albums_album_7904f807" ON "albums_album" ("artist_id");
COMMIT;
But, When I go to the database, directly to the database structure that Django bring me, I see that the slug field is not effective... This can detail them in this url https://cldup.com/-F9SQ2D3W8.jpeg
With the order to test that this slug works I create the url "albums" which point to the AlbumListView class based view
from django.conf.urls import patterns, url
from artists.views import AlbumListView
urlpatterns = patterns('',
url(r'^albums/$', AlbumListView.as_view(), name='album_list'),
url(r'^albums/(?P<artist>[\w\-]+)/$', AlbumListView.as_view(), name='album_list'),
)
The class based view AlbumListView is the following: Here I define a queryset for recovery the albums of an artist and with the kwargs variable is the way in how take
class AlbumListView(ListView):
model = Album
template_name = 'album_list.html'
def get_queryset(self):
if self.kwargs.get('artist'):
queryset = self.model.objects.filter(artist__slug=self.kwargs['artist'])
else:
queryset = super(AlbumListView, self).get_queryset()
return queryset
When I go to the view /albums in my browser, I see this message:
no such column: albums_album.slug
This is the image of error in my browser, Check out this url please:
What can be my problem? Why the migration doesn't works?
Thanks for your orientation :)
Looks like you added slug to model AFTER run syncdb and BEFORE run convert_to_south. Specifically about your case south's developer displays a warning message in the console:
Note that South assumed the application's models matched the
database(i.e. you haven't changed it since last syncdb); if you have,
you should delete the albums/migrations directory, revert models.py so
it matches the database, and try again.
For fixing your problem, you should:
Drop SlugField from Album (looks in your console output you should drop artist too)
Drop migrations folder from albums app
Run ./manage.py convert_to_south albums
Run ./manage.py migrate albums
Add SlugField
Run ./manage.py schemamigration albums --auto(Specify default value as '')
Run ./manage.py migrate albums
Profit!
To output my database to json file I would usually do
python manage.py dumptdata --indent=4 > mydata.json
However upon executing the following two commands to setup south:
python manage.py schemamigration myproj --initial
python manage.py migrate myproj --fake
I noticed that two of my booleans in mytable for an entry were switched from FALSE to TRUE! I see that from my GUI Web Interface interacting with the database however to more closely compare what changed and got corrupted I'd like to compare json to json but with south enabled I can no longer use the above command as it tells me
Not synced (use migrations):
- myproj
My table that had entries affected is below, I could have more affected data that I have not uncovered.
class MyConfig(models.Model):
name = models.CharField(max_length=64)
myConfigName = models.CharField(max_length=64, unique=True)
myA = models.ForeignKey(MyA)
myB = models.ForeignKey(MyB)
myBoolA = models.BooleanField()
myBoolB = models.BooleanField()
myBoolC = models.BooleanField()
class Meta:
unique_together = ('name', 'myA', 'myB')
def __unicode__(self):
return '%s_%s_%s' % (self.myA.name, self.myB.name, self.name)
schemamigration and migrate --fake don't modify the database. Do you have any initial_data fixture that could be reloaded when migrating? See https://docs.djangoproject.com/en/1.3/howto/initial-data/
Try to migrate with:
python manage.py migrate --no-initial-data
see south doc for more info about options
I don't think that either an --initial or a --fake should alter the database at all, so I'm surprised that it would modify data. In terms of why you're getting the "Not synced (use migrations)" error, I think it's likely because you faked the initial migration.
Try un-migrating the --fake and re-applying the initial migration with
python manage.py migrate --fake zero
python manage.py migrate
Then, you should be able to do the dumptdata