python - 在批量python中创建资源时如何跳过现有对象实例

Posted

技术标签:

【中文标题】python - 在批量python中创建资源时如何跳过现有对象实例【英文标题】:How to skip an existing object instance when creating resources in bulk python 【发布时间】:2019-06-06 03:52:57 【问题描述】:

我正在尝试批量创建资源。在创建资源时,我有 matric_no 必须是唯一的。如果现有matric_no 的值与一些新条目一起上传,我会收到完整性错误 500,因为该值已经存在并且它会阻止创建其余值。如何遍历这些值,然后检查该值是否存在,然后跳过以便可以填充其他值?这是我的代码:

**models.py**

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible
class Undergraduate(models.Model):

    id = models.AutoField(primary_key=True)
    surname = models.CharField(max_length=100)
    firstname = models.CharField(max_length=100)
    other_names = models.CharField(max_length=100, null=True, blank=True)
    card = models.CharField(max_length=100, null=True, blank=True)
    matric_no = models.CharField(max_length=20, unique=True)
    faculty = models.CharField(max_length=250)
    department_name = models.CharField(max_length=250)
    sex = models.CharField(max_length=8)
    graduation_year = models.CharField(max_length=100)
    mobile_no = models.CharField(max_length=150, null=True, blank=True)
    email_address = models.CharField(max_length=100)
    residential_address = models.TextField(null=True, blank=True)
    image = models.CharField(max_length=250, 
    default='media/undergraduate/default.png', null=True, blank=True)

    def __str__(self):
        return "Request: ".format(self.matric_no)


***serializers.py***

from .models import Undergraduate
from .models import Undergraduate

class UndergraduateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Undergraduate
        fields ='__all__'


class CreateListMixin:    
    """Allows bulk creation of a resource."""    
    def get_serializer(self, *args, **kwargs):

        if isinstance(kwargs.get('data', ), list):
            print(list)
            kwargs['many'] = True

        return super().get_serializer(*args, **kwargs)

**api.py**

from .models import Undergraduate

from rest_framework.viewsets import ModelViewSet

from .serializers import CreateListMixin,UndergraduateSerializer


class UndergraduateViewSet(CreateListMixin, ModelViewSet):

    queryset = Undergraduate.objects.all()
    serializer_class = UndergraduateSerializer
    permission_classes = (permissions.IsAuthenticated,)

**urls.py**

from rest_framework.routers import DefaultRouter
from .api import UndergradMassViewSet 
router=DefaultRouter() 

router.register(r'ug', UndergradMassViewSet) 

这是更新后的serializer.py

class UndergraduateSerializer(serializers.ModelSerializer):

    class Meta:
        model = Undergraduate
        fields = ('id', 'surname', 'firstname', 'other_names', 'card','matric_no', 'faculty', 'department_name', 'sex', 'graduation_year', 'mobile_no', 'email_address', 'residential_address')

        def create(self, validated_data):
            created_ids = []
            for row in validated_data:
                try:
                    created = super().create(row)
                    created_ids.append(created.pk)
                except IntegrityError:
                    pass
            return Undergraduate.objects.filter(pk__in=[created_ids])

这就是我现在移动它的方式 序列化器.py

class UndergraduateSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        created_ids = []
        for row in validated_data:
            try:
                created = super().create(row)
                created_ids.append(created.pk)
            except IntegrityError:
            pass
        return Undergraduate.objects.filter(pk__in=[created_ids])

class Meta:
    model = Undergraduate
    fields = ('id', 'surname', 'firstname', 'other_names', 'card','matric_no', 'faculty', 'department_name', 'sex', 'graduation_year', 'mobile_no', 'email_address', 'residential_address')
    read_only_fields = ('id',)

当发送的列表已经存在matric_no时,返回500 ListSeriaizer is not iterable

【问题讨论】:

更新的序列化程序出现什么错误? 错误代码:500 List Serializer 对象不可迭代 不要将代码放在 Meta 类中。直接放到序列化器类中 @ChiomaIgbokwe 有什么改善吗?? @Ken4scholars 还没有,同样的错误,ListSerializer 对象不可迭代 【参考方案1】:

你必须在你的序列化器中实现一个自定义的create() 方法来处理这种情况,因为序列化器的默认创建方法需要一个对象。

不过,这里有几个设计决策需要考虑:

    您可以使用bulk_create,但它有很多文档中列出的警告,并且由于插入是在一次提交中完成的,因此仍然会引发完整性错误。这里唯一的优势是速度 您可以遍历每个对象并单独创建它们。这将解决完整性问题,因为您可以捕获完整性异常并继续前进。在这里你会在 1 内失去速度 您还可以在继续创建之前检查 validate 方法中的完整性问题。这样,您可以立即向客户端返回错误响应,其中包含有关违规 ro 的信息。如果一切正常,那么您可以使用 1 或 2 来创建对象。

就个人而言,我会选择 2(也可以选择 3)。假设您也决定选择它,您的序列化程序的 create 方法应如下所示:

def create(self, validated_data):
    created_ids = []
    for row in validated_data:
        try:
            created = super().create(row)
            created_ids.append(created.pk)
        except IntegrityError:
            pass
    return Undergraduate.objects.filter(pk__in=[created_ids])

所以在这种情况下,只有创建的对象会作为响应返回

【讨论】:

我尝试了自定义创建我仍然得到 500 ListSerializer object is not iterable 请贴出代码。我怀疑您正在尝试迭代序列化程序对象而不是迭代validated_data

以上是关于python - 在批量python中创建资源时如何跳过现有对象实例的主要内容,如果未能解决你的问题,请参考以下文章

在python中使用win32在内存中创建一个图标

python 在python中创建计数器

如何在 Python 中创建 GUID/UUID

在 Python 中创建一个新字典

在 Anaconda 中创建 python 3.3 环境

如何在python中创建一个zip文件