在Django View中将用户/帐户表添加到Postgres

时间:2011-11-07 16:07:55

标签: python django postgresql django-views

转到编辑2

在views.py中调用以下adduser函数。我首先保存用户,因为它的id(由INSERT上的Django自动创建)是帐户和密码的主/外键。添加用户似乎工作正常,但是当它到达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".

但关键应该在那里,因为它只是将用户保存到db ...

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个用户会抛出一个错误,即没有id为5(duh)的用户。我没有在代码中看到任何会导致它搜索user_id + 1,任何想法的内容

到战争的胸膛!

4 个答案:

答案 0 :(得分:4)

我的钱是拼写错误的名字。我在错误消息中注意到你有

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更新)。可能会带领你......

您还可以使用标准命令行客户端(交互式终端)psql的元命令\d

我会运行一个测试用例并让postgres服务器记录它获得的所有内容。为此目的设置此参数:

set log_statement = 'all';

手册about logging-parameters

  

log_statement(enum)

     

控制记录哪些SQL语句。有效值为none(off),ddl,mod和all(所有语句)。

how to set parameters上的手册。

答案 1 :(得分:0)

我看不出您提供的导致该错误的代码有什么问题,但有些事情与recommended method

有所不同

您似乎正在使用ForeignKey关系 - 这可能不是您想要的,除非您计划将单个用户链接到多个帐户。 OneToOne关系可能就是你想要的,除非是这种情况。

使用Handler创建与User关联的Account似乎是一种更好的方法来处理事情 - 因为django将处理调用处理程序,而不是你必须记住调用适当的代码。虽然这是否能解决你的问题,但我不太确定

This part of the manual建议您在调用create_user之后不需要调用u.save(),除非您在创建用户后对其进行了更改。

答案 2 :(得分:0)

尝试以这种方式装饰你的功能:

from django.db import transaction

 @transaction.autocommit
 def adduser(request):
使用postgres的django默认是使用视图启动事务并在结束时提交它(例外是回滚)。

所以.saved()对象并不总是你期望它们......

答案 3 :(得分:0)

一些注释在帐户中使用OneToOneField modeland userprofile https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User.get_profile 并为保存帐户节省信号

您可以通过这种方式使用保存用户。 Pylint说这不好,但在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