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

Posted

技术标签:

【中文标题】在 Django 视图中将用户/帐户表添加到 Postgres【英文标题】:Adding a user/accounts table to Postgres in Django View 【发布时间】:2011-12-23 18:11:39 【问题描述】:

进入编辑 2

在views.py 中调用如下adduser 函数。我首先保存用户,因为它的 id(由 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 个用户会引发一个错误,即没有 id 为 5 的用户(duh)。我在代码中没有看到任何会导致它搜索 user_id+1 的任何想法

到战争基金!

【问题讨论】:

Accounts 是什么对象? Accounts 是一个类似于 User 的模型,只是有大量不同的字段用于社交、媒体和电子邮件用户名。 u.save() 不需要,因为create_user() 应该已经将其提交到数据库。您可能应该在 Accounts 模型中显示 user 字段。你有自己的用户模型吗? user = models.ForeignKey(User) 用户模型是 Django 的默认值。您确定 create_user 保存了吗?我之前在一次初始化所有三个表然后保存时遇到了问题,因为它显示了类似的东西,在创建帐户或密码之前推送 u.save() 修复它。 您是否使用位于 contrib.auth.models 中的用户模型?因为错误说:“OmniCloud_App_user”而不是“OmniCloud_auth_user” 【参考方案1】:

很少有 cmets 在帐户模型和用户配置文件中使用 OneToOneField 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

【讨论】:

【参考方案2】:

我的钱在一个拼写错误的名字上。我在错误消息中注意到您有

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(枚举)

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

how to set parameters上的手册。

【讨论】:

我会尽快调查,但要回答你最后一个问题,我知道正在创建用户,因为当我尝试通过重新填写注册页面进行调试和测试时,Key (user_id)=(4) 每次都会递增应该,并且尝试注册相同的用户名会拒绝。所以添加的是用户,而不是帐户。 我在那里添加了 Accounts 的初始化。 User 是我没有声明的模型(Django 内置模型)。 Django 是否将其作为用户保存到数据库中,即使您导入用户来使用它? @Cris:我更新了我的答案并提供了一些帮助来分析问题。对于 Django 内部,我帮不了你太多。不是我的专业领域。 我能得到的最接近答案的是这个。可能是我曾经有一个自定义用户表,在安装默认的 Django 时没有正确删除。无论如何,你给了一个非常彻底的答案,所以很高兴赏金!【参考方案3】:

试着用这种方式装饰你的函数:

from django.db import transaction

 @transaction.autocommit
 def adduser(request):

django 默认使用 postgres 启动一个带有视图的事务并在最后提交(例外是回滚)。

所以 .saved() 对象并不总是你期望的那样......

【讨论】:

所以我不会调用 u.save 因为它会自动保存?【参考方案4】:

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

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

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

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

【讨论】:

以上是关于在 Django 视图中将用户/帐户表添加到 Postgres的主要内容,如果未能解决你的问题,请参考以下文章

用户在表格视图控制器中将行/部分添加到静态单元格

在 django 中将自定义字段添加到 auth_user 表

在Django中将计算值从视图保存到模型

text 在Swift中将搜索栏添加到表视图

如何在 django 中将图像添加到帖子中

如何从表中将列添加到现有视图? [复制]