Добавление таблицы пользователей / учетных записей в Postgres в Django View - PullRequest
5 голосов
/ 07 ноября 2011

Перейти к редактированию 2

Вызов следующей функции adduser в views.py.Сначала я сохраняю пользователя, потому что его идентификатор (автоматически созданный Django после INSERT) является первичным / внешним ключом для учетных записей и паролей.Добавление пользователя, кажется, работает нормально, но затем, когда он достигает значения Accounts(user=u), выдается следующая ошибка:

IntegrityError at /adduser
insert or update on table "OmniCloud_App_accounts" violates foreign key constraint "user_id_refs_id_468fbcec324e93d2"
DETAIL:  Key (user_id)=(4) is not present in table "OmniCloud_App_user".

Но ключ должен быть там, поскольку он просто сохранил пользователя в БД...

def adduser(request):
    username = request.POST['username']
    password = request.POST['password']
    u = User.objects.create_user(username, request.POST['email'], password)
    u.save()
    a = Accounts(user=u)
    p = Passwords(user=u)
    a.save()
    p.save()
    user = authenticate(username=username, password=password)
    if user is not None and user.is_active:
        auth.login(request, user)
        return HttpResponseRedirect("/%s/" %u.id)
    else:
        return HttpResponseRedirect("/account/invalid/")

РЕДАКТИРОВАТЬ: Вот начало инициализации учетных записей:

from django.db import models
from django.contrib.auth.models import User
class Accounts(models.Model):   
    user = models.ForeignKey(User)

РЕДАКТИРОВАТЬ 2 Я понял, зайдя на страницу администратора, когда он жалуется, что 4 отсутствует в базе данных, это потому, что он добавляет третьего пользователя.Добавление 4-го пользователя приводит к ошибке, что нет пользователя с идентификатором 5 (дух).Я не вижу в коде ничего, что могло бы заставить его искать user_id + 1, какие-либо идеи

К боевому сундуку!

Ответы [ 4 ]

4 голосов
/ 10 ноября 2011

Мои деньги на имя с ошибкой. Я замечаю в сообщении об ошибке, что у вас есть

OmniCloud_App_accounts
OmniCloud_App_user

Вторая таблица использует единственное число. Второй такой таблицы случайно нет:

OmniCloud_App_users

Кроме того, использование идентификаторов со смешанным регистром в PostgreSQL является отличным источником репутации здесь, в SO. Это укусит вас рано или поздно. Жертвы этой глупости здесь постоянные. Может быть, есть любая таблица с таким именем - а вы где-то забыли двойные кавычки в "OmniCloud_App_user"?

omnicloud_app_user

Это либо так, либо транзакция, спасающая пользователя, еще не зафиксирована. Можете ли вы только создать пользователя (и еще без учетных записей) и проверить, попал ли он в нужную базу данных в таблице и с правильным ID?

Редактировать: инструменты для диагностики проблемы

Если вы знаете , что создаются пользователи, тогда возникает вопрос: есть ли внешний ключ? ограничение user_id_refs_id_468fbcec324e93d2 посмотрите в нужном месте? Та же база? Та же схема? Та же таблица?

Чтобы выяснить, какие таблицы существуют в вашей базе данных, попробуйте следующий запрос (если у вас есть необходимые права):

SELECT n.nspname AS schema_name
      ,c.relname AS table_name
      ,c.relhastriggers
      ,c.reltuples
FROM   pg_catalog.pg_class c
LEFT   JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relname ~~* '%user%'
AND    c.relkind = 'r'
AND    nspname <> 'pg_catalog';

Показывает все таблицы во всех схемах, в имени которых указано «user», без учета регистра. Плюс, если в таблице есть триггеры ( может вызвать вашу проблему) и сколько строк в ней (оценка обновлена ​​на ANALYZE). Мог бы дать вам преимущество ...

Вы также можете использовать мета-команду \d стандартного клиента командной строки (интерактивный терминал) psql.

Я бы запустил тестовый пример и велел бы серверу postgres регистрировать все, что он получает. Для этого установите этот параметр:

set log_statement = 'all';

Инструкция о параметрах регистрации .

log_statement (enum)

Управляет записью операторов SQL. Допустимые значения: none (выкл), ddl, mod и все (все операторы).

Инструкция по как настроить параметры .

0 голосов
/ 15 ноября 2011

несколько комментариев Использовать OneToOneField в аккаунтах modeland userprofile https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User.get_profile и сделать сохранение сигнала для сохранения аккаунта

Вы можете использовать сохранение пользователя таким образом. Пилинт говорит, что это не хорошо, но так же, как и в Django

try:
    user = User.objects.create(**request.POST) #better way save from forms, no the forms is best way 
except:
    #exception logic
    pass
else:
    auth.login(request, user)

так что если вы используете формы

form = UserForm(request.POST or None)
if form.is_valid():
    user = form.save()
    auth.login(request, user)
else:
    #invalid data logic
    pass
0 голосов
/ 10 ноября 2011

Попробуйте оформить свою функцию следующим образом:

from django.db import transaction

 @transaction.autocommit
 def adduser(request):

По умолчанию django с postgres запускает транзакцию с представлением и фиксирует ее в конце (за исключением откатов).

такОбъекты .saved () не всегда соответствуют вашим ожиданиям ...

0 голосов
/ 10 ноября 2011

Я не вижу ничего плохого в предоставленном вами коде, который мог бы вызвать эту ошибку, но есть несколько вещей, которые вы делаете не так, как рекомендуемый метод

Похоже, вы используете отношение ForeignKey - это может быть не то, что вам нужно, если только вы не планируете связать одного пользователя с несколькими учетными записями. Отношения OneToOne, вероятно, то, что вы хотите, если это не так.

Использование обработчика для создания учетной записи, связанной с пользователем, также кажется лучшим способом справиться с ситуацией - поскольку django будет иметь дело с вызовом обработчика, а не с тем, чтобы вы не забывали вызывать соответствующий код. Хотя это решит твою проблему, я не уверен,

В этой части руководства предполагается, что вам не нужно вызывать u.save () после вызова create_user, если только вы не изменили пользователя с момента его создания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...