【问题标题】:How do you use the migration framework to add Django REST Framework Authentication Tokens如何使用迁移框架添加 Django REST 框架身份验证令牌
【发布时间】:2015-12-19 19:52:53
【问题描述】:

我正在使用 Django REST 框架设置一个新的 API,我需要向所有现有用户添加 Auth 令牌。文档说要做:

from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

for user in User.objects.all():
    Token.objects.get_or_create(user=user)

但理想情况下,这应该使用 Django 的新迁移框架来实现。

有没有简单的方法可以做到这一点?

【问题讨论】:

    标签: django django-rest-framework django-migrations http-token-authentication


    【解决方案1】:

    这里的诀窍是知道Token 使用自定义save() 方法来生成唯一的token.key,但自定义save() 方法不在迁移中运行。因此,第一个令牌将有一个空白键,而第二个令牌将失败并显示 IntegrityError,因为它们的键也是空白且不唯一。

    相反,将generate_key() 代码复制到您的迁移中,如下所示:

    # Generated with `manage.py makemigrations --empty YOUR-APP`.
    
    import binascii
    import os
    
    from django.db import migrations
    
    # Copied from rest_framework/authtoken/models.py.
    def generate_key():
        return binascii.hexlify(os.urandom(20)).decode()
    
    def create_tokens(apps, schema_editor):
        User = apps.get_model('auth', 'User')
        Token = apps.get_model('authtoken', 'Token')
        for user in User.objects.filter(auth_token__isnull=True):
            token, _ = Token.objects.get_or_create(user=user, key=generate_key())
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('YOUR-APP', 'YOUR-PREVIOUS-MIGRATION'),
        ]
    
        operations = [
            migrations.RunPython(create_tokens),
        ]
    

    您应该避免将 rest_framework 代码直接导入迁移中,否则有一天您的迁移将无法运行,因为您决定删除 rest_framework 或更改库的界面。迁移需要及时冻结。

    【讨论】:

      【解决方案2】:

      首先为您希望使用它的应用创建一个空迁移。就我而言,我有一个名为 users 的应用程序,这种东西就在其中,所以我跑了:

      manage.py makemigrations users --empty
      

      这在我的迁移目录中创建了一个新文件,我可以使用以下内容对其进行更新:

      # -*- coding: utf-8 -*-
      from __future__ import unicode_literals
      
      from django.db import models, migrations
      from rest_framework.authtoken.models import Token
      from django.contrib.auth.models import User
      
      def add_tokens(apps, schema_editor):
          print "Adding auth tokens for the API..."
          for user in User.objects.all():
              Token.objects.get_or_create(user=user)
      
      def remove_tokens(apps, schema_editor):
          print "Deleting all auth tokens for the API..."
          Token.objects.all().delete()
      
      class Migration(migrations.Migration):
      
          dependencies = [
              ('users', '0002_load_initial_data'),
          ]
      
          operations = [
              migrations.RunPython(add_tokens, reverse_code=remove_tokens),
          ]
      

      【讨论】:

      • 您不应将代码导入迁移中,否则在您决定删除rest_frameworkrest_framework 接口更改后的某一天,您的迁移将开始失败。迁移需要完全独立。
      猜你喜欢
      • 2023-03-16
      • 1970-01-01
      • 2014-04-14
      • 2018-12-15
      • 1970-01-01
      • 2014-01-31
      • 2013-06-29
      • 2017-09-26
      • 2017-11-02
      相关资源
      最近更新 更多