2013-02-27 25 views
23

Najwyraźniej po dodaniu mojej nowej tablicy użytkowników do witryny, django_admin_log nadal ma tabelę FK do auth_user. Jakikolwiek sposób rozwiązać ten problem? Nie widziałem tego problemu w inscenizacji lub lokalnie, więc musiało się wydarzyć coś dziwnego.Błąd integralności na django_admin_log po aktualizacji istniejącej witryny do nowego modelu użytkownika Django 1.5

Traceback (najnowsza wezwanie ostatni) :

File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response response = callback(request, *callback_args, **callback_kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-1.10.0.28/newrelic/api/object_wrapper.py", line 220, in call self._nr_instance, args, kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-1.10.0.28/newrelic/hooks/framework_django.py", line 475, in wrapper return wrapped(*args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/admin/options.py", line 372, in wrapper return self.admin_site.admin_view(view)(*args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view response = view_func(request, *args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/views/decorators/cache.py", line 89, in _wrapped_view_func response = view_func(request, *args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 202, in inner return view(request, *args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py", line 25, in _wrapper return bound_func(*args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view response = view_func(request, *args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py", line 21, in bound_func return func(self, *args2, **kwargs2)

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/transaction.py", line 223, in inner return func(*args, **kwargs)

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/transaction.py", line 217, in exit self.exiting(exc_value, self.using)

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/transaction.py", line 281, in exiting commit(using=using)

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/transaction.py", line 152, in commit connection.commit()

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/init.py", line 241, in commit self._commit()

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 242, in _commit six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])

File "/app/.heroku/python/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 240, in _commit return self.connection.commit()

File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-1.10.0.28/newrelic/hooks/database_dbapi2.py", line 68, in commit return self._nr_connection.commit()

IntegrityError: insert or update on table "django_admin_log" violates foreign key constraint "django_admin_log_user_id_fkey" DETAIL: Key (user_id)=(2) is not present in table "auth_user".

Odpowiedz

18

że ponieważ tabela django_admin_log nadal zawiera klucz obcy relacji do starego auth_user tabeli.

Musisz upuścić i ponownie utworzyć stół.

$ heroku pg:psql 
psql => drop table django_admin_log; 

Dla Django < 1,7

$ heroku run python manage.py syncdb 

I Django> = 1,7

$ ./manage.py sqlmigrate admin 0001 | heroku pg:psql 

I to wszystko :)

EDITED with @dustinfarris Django 1.7+ answer precision

0

Wydaje się, jakby nie mogło być złe transakcję jako pewnym momencie podczas uruchamiania tego, można spróbować całkowicie zresetować db z :

heroku pg:reset 

Albo można próbować pSQL do bazy danych i sprawdzić/skorygować dane tworząc ów problem (co jest prawdopodobne, że jego próby wstawienia tego samego użytkownika dwa razy) :

heroku pg:psql 
0

myślę, że administrator aplikacji tylko instalacje Tabela django_admin_log.

python manage.py sqlclear admin 

BEGIN; 
DROP TABLE "django_admin_log"; 

COMMIT; 

Możesz także spróbować.

python manage.py sqlclear admin | python manage.py dbshell 
python manage.py syncdb 
30

Jeśli napotkasz ten i używasz> = 1,7:

./manage.py dbshell 

DROP TABLE django_admin_log; 

, a następnie:

./manage.py sqlmigrate admin 0001 | ./manage.py dbshell 
+2

Świetne rozwiązanie! –

+0

Pracowałem dla mnie używając 1.8.2. Byłoby najlepiej, gdybyś dodał to, co faktycznie robi. – Frankline

+0

Dla nowego projektu z 'django 1.10.1', zrobiłem kroplę w sposób opisany, ale zamiast komendy' sqlimigrate' na końcu użyłem prostej komendy 'migrate'. Tak więc wyglądało to jak "migracja-> błąd-> upuszczenie-> migracja". – alxs

6

Jeśli jesteś w Django 1.7 lub nowszej, dodając właściwy Migracja do zmiany tabeli django_admin_log jest znacznie lepszą opcją w mojej opinii. W ten sposób możesz zachować wszystkie istniejące wpisy dziennika, które w rzeczywistości mogą być czymś, czego używasz. Wykonanie takiej zmiany wymaga, aby pole id było takie samo, np. ma tę samą nazwę itp.

Najpierw trzeba dowiedzieć się nazwy ograniczenia, które mogą być wykonywane przez wchodząc w powłoce bazy danych:

./manage.py dbshell 

A potem opisując django_admin_log tabeli:

\d+ django_admin_log; 

ten będzie mieć ograniczenie na wyjściu, coś takiego:

"user_id_refs_id_c0d12874" FOREIGN KEY (user_id) REFERENCES my_custom_auth_model(id) DEFERRABLE INITIALLY DEFERRED 

Gdzie my_custom_auth_model to nazwa tabeli, w której znajduje się niestandardowy model autoryzacji, a user_id_refs_id_c0d12874 to nazwa ograniczenia, którą należy skopiować na później.

Następnie należy utworzyć nową migrację:

./manage makemigrations --empty my_custom_auth_model 

I przemianowany na moją nową migrację (tj 0000_alter_admin_log_constraint.py), aby mieć coś pożytecznego zamiast DATESTAMP w pliku. Nie stosować cztery zera choć używanie cokolwiek został przydzielony podczas tworzenia migracji :)

W nowej migracji, to jest to, co służy do operacji:

operations = [ 
    migrations.RunSQL(
     '''ALTER TABLE django_admin_log DROP CONSTRAINT user_id_refs_id_c0d12874''', 
     reverse_sql='''ALTER TABLE django_admin_log ADD CONSTRAINT user_id_refs_id_c0d12874 
      FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED'''), 
    migrations.RunSQL(
     '''ALTER TABLE django_admin_log ADD CONSTRAINT user_id_refs_id_c0d12874 
      FOREIGN KEY (user_id) REFERENCES my_custom_auth_model(id) DEFERRABLE INITIALLY DEFERRED''', 
     reverse_sql='''ALTER TABLE django_admin_log DROP CONSTRAINT user_id_refs_id_c0d12874'''), 
] 

Zastępca user_id_refs_id_c0d12874 z ograniczeniem cokolwiek nazwa skopiowany poprzednio. Jak widać, te dwie operacje i ich rewersy są odwrotne względem siebie, co oznacza, że ​​możesz przenieść te migracje również w tył.

Teraz, wszystko co musisz zrobić, to zastosować nową migracją:

./manage.py migrate 

tabela django_admin_log należy teraz ponownie użytkowej i nic na piśmie administratorowi będzie działać zamiast braku z IntegrityError.

+0

Nie jest to najprostsze rozwiązanie, ale przynajmniej zapisuje dane w dzienniku administratora! – mennanov

+0

Nie sądzę, że jest to bezpieczne, aby kodować nazwy ograniczeń w migracji. To nie jest przenośne. –

+0

Dzięki. Ja też uważam, że posiadanie pliku migracji jest sposobem na to, że pomogło mi to –

Powiązane problemy