【问题标题】:How to load sql fixture in Django for User model?如何在 Django 中为用户模型加载 sql 夹具?
【发布时间】:2011-01-25 14:54:41
【问题描述】:

有谁知道如何使用 sql 固定装置为 auth.User 加载初始数据? 对于我的模型,我刚刚在名为 sql 的文件夹中有一个 .sql 文件,syncdb 做得很好。但我不知道如何为 auth.User 模型做这件事。我用谷歌搜索了它,但没有成功。

提前致谢,

阿尔多

【问题讨论】:

    标签: sql django fixtures fixture


    【解决方案1】:

    对于 SQL 固定装置,您必须专门为 auth 表提供插入语句。您可以使用命令python manage.py sql auth 找到身份验证表的架构。

    更简单且独立于数据库的方法(除非您想运行一些额外的 SQL 魔术),只需在应用程序的 fixtures 目录中创建一个 JSON 或 YAML fixture 文件,其中包含如下数据:

    - model: auth.user
      pk: 100000
      fields:
        first_name: Admin
        last_name: User
        username: admin
        password: "<a hashed password>"
    

    您可以在 django shell 中快速生成散列密码

    >>> from django.contrib.auth.models import User
    >>> u = User()
    >>> u.set_password('newpass')
    >>> u.password
    'sha1$e2fd5$96edae9adc8870fd87a65c051e7fdace6226b5a8'
    

    每当您运行 syncdb 时,它都会被加载。

    【讨论】:

      【解决方案2】:

      您正在寻找loaddata:

      manage.py loadata path/to/your/fixtureFile
      

      但我认为该命令只能处理 XML、YAML、Python 或 JSON 格式的文件 (see here)。要创建此类适当的文件,请查看 dumpdata 方法。

      【讨论】:

      • 我知道,但是,有没有办法自动化它,就像在 syncdb 中调用普通灯具一样?
      【解决方案3】:

      有一个技巧:(在 Django 1.3.1 上测试)

      解决方案:

      1. python manage.py startapp auth_fix
      2. mkdir auth_fix/fixtures
      3. python manage.py dumpdata auth &gt; auth_fixtures/fixtures/initial_data.json
      4. Include auth_fix in INSTALLED_APPS inside settings.py

      下次运行python manage.py syncdb时,Django 会自动加载身份验证装置。

      说明:

      1. 只需创建一个空应用程序来保存灯具文件夹。将 __init__py、models.py 和 views.py 留在其中,以便 Django 将其识别为应用程序而不仅仅是文件夹。
      2. 在应用中制作fixtures文件夹。
      3. python manage.py dumpdata auth 将在数据库中转储“auth”数据以及所有组和用户信息。该命令的其余部分只是将输出重定向到一个名为“initial_data.json”的文件中,这是 Django 在运行“syncdb”时查找的文件。
      4. 只需在 settings.py 中的 INSTALLED_APPS 中包含 auth_fix。

      这个示例展示了如何在 JSON 中执行此操作,但您基本上可以使用您选择的格式。

      【讨论】:

      • 我喜欢这个开箱即用的修复。顺便说一句,如果你有南,请参阅here 以允许夹具仅加载一次。
      【解决方案4】:

      感谢您的回答。我找到了适合我的解决方案,巧合的是布赖恩的建议之一。这里是:

      首先,我在syncdb 之后断开了创建超级用户的信号,因为我的超级用户在我的auth_user 装置中:

      models.py

      from django.db.models import signals
      from django.contrib.auth.management import create_superuser
      from django.contrib.auth import models as auth_app
      
      
      signals.post_syncdb.disconnect(
          create_superuser,
          sender=auth_app,
          dispatch_uid = "django.contrib.auth.management.create_superuser")
      

      然后我创建了一个在syncdb之后调用的信号:

      //management/__init__.py

      """
      Loads fixtures for files in sql/<modelname>.sql
      """
      from django.db.models import get_models, signals
      from django.conf import settings 
      import <myproject>.<myapp>.models as auth_app
      
      def load_fixtures(app, **kwargs):
          import MySQLdb
          db=MySQLdb.connect(host=settings.DATABASE_HOST or "localhost", \
             user=settings.DATABASE_USER,
          passwd=settings.DATABASE_PASSWORD, port=int(settings.DATABASE_PORT or 3306))
      
          cursor = db.cursor()
      
          try:
              print "Loading fixtures to %s from file %s." % (settings.DATABASE_NAME, \
                  settings.FIXTURES_FILE)
              f = open(settings.FIXTURES_FILE, 'r')
              cursor.execute("use %s;" % settings.DATABASE_NAME)
              for line in f:
                  if line.startswith("INSERT"):
                      try:
                          cursor.execute(line)
                      except Exception, strerror:
                          print "Error on loading fixture:"
                          print "-- ", strerror
                          print "-- ", line
      
              print "Fixtures loaded"
      
          except AttributeError:
              print "FIXTURES_FILE not found in settings. Please set the FIXTURES_FILE in \
                  your settings.py" 
      
          cursor.close()
          db.commit()
          db.close()
      
      signals.post_syncdb.connect(load_fixtures, sender=auth_app, \
          dispatch_uid = "<myproject>.<myapp>.management.load_fixtures")
      

      在我的 settings.py 中,我添加了 FIXTURES_FILE 以及带有 sql 转储的 .sql 文件的路径。

      我还没有找到的一件事是如何仅在创建表后触发此信号,而不是每次触发 syncdb。一个临时解决方法是在我的 sql 命令中使用 INSERT IGNORE INTO。

      我知道这个解决方案远非完美,非常欢迎批评/改进/意见!

      问候,

      阿尔多

      【讨论】:

        【解决方案5】:

        一个选项是手动导入您的 auth.User SQL,然后将其转储到标准 Django 夹具(如果您希望 syncdb 找到它,请将其命名为 initial_data)。您通常可以将此文件放入任何应用程序的固定器目录中,因为固定器数据都将使用正确的 app_label 键入。或者您可以创建一个空/虚拟应用并将其放置在那里。

        另一个选项是覆盖 syncdb 命令并以您认为合适的方式应用夹具。

        我同意 Felix 的观点,即 Django 中没有用于使用 SQL 填充 contrib 应用程序的非平凡自然钩子。

        【讨论】:

          【解决方案6】:

          如果你碰巧用 south 做数据库迁移,创建用户非常简单。

          首先,创建一个裸数据迁移。它需要包含在某些应用程序中。如果您有一个放置共享代码的通用应用程序,那将是一个不错的选择。如果您有一个应用程序可以集中与用户相关的代码,那就更好了。

          $ python manage.py datamigration <some app name> add_users
          

          相关的迁移代码可能如下所示:

          # encoding: utf-8
          import datetime
          from south.db import db
          from south.v2 import DataMigration
          from django.db import models
          from django.contrib.auth.models import User
          
          class Migration(DataMigration):
          
              users = [
                  {
                      'username': 'nancy',
                      'email': 'nancy@example.com',
                      'password': 'nancypassword',
                      'staff': True,
                      'superuser': True
                  },
                  {
                      'username': 'joe',
                      'email': '',
                      'password': 'joepassword',
                      'staff': True,
                      'superuser': False
                  },
                  {
                      'username': 'susan',
                      'email': 'susan@example.com',
                      'password': 'susanpassword',
                      'staff': False,
                      'superuser': False
                  }
              ]
          
              def forwards(self, orm):
                  """
                  Insert User objects
                  """
                  for i in Migration.users:
                      u = User.objects.create_user(i['username'],  i['email'], i['password'])
                      u.is_staff = i['staff']
                      u.is_superuser = i['superuser']
                      u.save()
          
              def backwards(self, orm):
                  """
                  Delete only these users
                  """
                  for i in Migration.users:
                      User.objects.filter(username=i['username']).delete()
          

          然后简单地运行迁移并且应该插入 auth 用户。

          $ python manage.py migrate <some app name>
          

          【讨论】:

            【解决方案7】:

            我只是将 SQL 语句添加到另一个模型的自定义 sql 文件中。我选择了我的 Employee 模型,因为它依赖于 auth_user。 我编写的自定义 SQL 实际上是从我的旧应用程序中读取并从中提取用户信息,并使用 REPLACE 而不是 INSERT(我使用的是 MySQL),因此我可以随时运行它。 我将 REPLACE...SELECT 语句放在一个过程中,以便手动运行或使用 cron 调度。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-10-30
              • 2017-07-20
              • 2018-03-03
              • 2013-03-06
              • 1970-01-01
              • 2016-03-23
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多