【问题标题】:Is it possible to alter existing data with Django's fixtures?是否可以使用 Django 的固定装置更改现有数据?
【发布时间】:2012-08-22 18:56:12
【问题描述】:

我在测试中使用了 Django 的固定装置。我需要创建 UserProfile 夹具。第一个问题是它指向用户条目。为了处理它,我使用自然键。所以我只是说 UserProfile 夹具的用户字段是用户夹具的实际用户名。

[
    {
        "pk": 8002,
        "model": "auth.user",
        "fields": {
            "date_joined": "2012-08-28 10:00:00.000000+00:00",
            "email": "",
            "first_name": "",
            "groups": [],
            "is_active": true,
            "is_staff": false,
            "is_superuser": false,
            "last_login": "2012-08-28 10:00:00.000000+00:00",
            "last_name": "",
            "password": "pbkdf2_sha256$10000$ltmEKsdCPjuK$74ZwNUh8rqFAPZ6+Cmi3tc8A94ueeXTplFqOQKlY4hc=",
            "user_permissions": [],
            "username": "user8002"
        }
    },
    {
        "pk": null,
        "model": "spam_and_eggs.userprofile",
        "fields": {
            "user": ["user8002"],
            "language": "",
            "email_activated": true
        }
     }
]

不幸的是,它返回了一个错误:

IntegrityError: Could not load share4you.UserProfile(pk=None): column user_id is not unique

第二个问题来了。我认为它可能会失败,因为 UserProfile 是在使用 Django 的信号创建用户时自动创建的,而夹具失败,因为该用户的 UserProfile 已经创建。这可能是原因吗?有什么办法可以解决吗?

感谢您的任何建议!

编辑#1:

型号和信号:

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    language = models.CharField(max_length=255, null=True, blank=True)
    email_activated = models.BooleanField()

@receiver(post_save, sender=User)
def create_profile(instance, created, **kwargs):
    if created:
        UserProfile.objects.get_or_create(user=instance)

用户模型是django.contrib.auth.models.User

【问题讨论】:

  • 你能发布你的模型和信号接收器吗?

标签: python django json unit-testing fixtures


【解决方案1】:

是否可以使用 Django 的固定装置更改现有数据?

当然,如果一个夹具有一个存在于数据库中的 pk,django 会进行更新。

user = models.ForeignKey(User, unique=True)

这很有趣,为什么不是 OneToOneField 呢?

>>> a=User.objects.all()[0]

>>> a.userprofile_set.all()
[<UserProfile: UserProfile object>]

>> a.userprofile_set.create(language='bar')
IntegrityError: column user_id is not unique

IntegrityError:无法加载 share4you.UserProfile(pk=None):列 user_id 不是唯一的

  • 设置一个实整数而不是pk=null
  • 您应该设置"user": 8002,而不是"user": ["user8002"]

我认为它可能会失败,因为 UserProfile 是在使用 Django 的信号创建用户时自动创建的,而夹具失败是因为该用户的 UserProfile 已经创建。

我无法重现此行为。这些固定装置可以很好地加载和重新加载您的模型:

[
    {
        "pk": 1,
        "model": "auth.user",
        "fields": {
            "username": "jpic",
            "first_name": "",
            "last_name": "",
            "is_active": true,
            "is_superuser": true,
            "is_staff": true,
            "last_login": "2012-06-11T06:44:57.637Z",
            "groups": [],
            "user_permissions": [],
            "password": "pbkdf2_sha256$10000$KzsUTACvZgJU$qvywXdVv/N3s5lifS/gQxSGog36ExGbuj2U+IQ6aUNk=",
            "email": "t@tt.tt",
            "date_joined": "2012-06-11T06:44:57.637Z"
        }
    },
    {
        "pk": 1,
        "model": "test_app.userprofile",
        "fields": {
            "language": "example.com",
            "user": 1
        }
    }
]

此外,还有另一种可能使用 django-annoying 创建 UserProfile 类:

from annoying.fields import AutoOneToOneField


class UserProfile(models.Model):
    user = AutoOneToOneField('auth.User', primary_key=True)
    home_page = models.URLField(max_length=255, blank=True)

【讨论】:

  • 谢谢,成功了!此外,这不是一对一的关系,因为用户可以拥有许多个人资料。 :)
  • 一个用户只能有一个配置文件,因为 UserProfile.user 是唯一的!
  • 只是为了澄清这个声明:“当然,如果一个夹具有一个存在于数据库中的 pk,django 将进行更新”为了清楚起见,我会添加 只要你指定字段。如果你不这样做,django 会清除它们。
【解决方案2】:

您可以在创建配置文件中检查原始参数。它表示,如果它来自固定装置,请查看this 了解更多详细信息。这样您就可以控制配置文件的创建。

【讨论】:

    【解决方案3】:

    我建议你也看看django-pyfixture。这将使您的数据看起来像固定装置,但更“智能”。

    【讨论】:

      猜你喜欢
      • 2011-09-01
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      • 2020-07-23
      相关资源
      最近更新 更多