忽略迁移中的Django模型字段

2024-09-30 02:34:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我想创建一个Django模型,其中包含一个FileField来存储图像和视频文件,但我想在保存实例之前验证这些文件。我考虑过添加三个字段:

  • file:一个FileField字段。这将只用于在数据库中具有file列,但序列化程序不会使用它(而是使用接下来的两个字段)
  • file_image:用于执行图像文件验证的ImageField。在保存模型实例之前,文件将被分配到file字段我不希望此字段具有dabatase表示形式
  • file_video:用于执行视频文件验证的VideoField(自定义字段)。在保存模型实例之前,文件将被分配到file字段我不希望此字段具有dabatase表示形式

当然,file_imagefile_video不会同时设置

问题是阻止makemigrations在迁移中包括file_imagefile_video。我可以手工编辑迁移文件,但不知是否有办法自动忽略这些字段

class MyModel(models.Model):
    file = models.ImageField()
    file_image = models.ImageField()    # Not an actual column
    file_video = models.VideoField()    # Not an actual column

    def save(self, *args, **kwargs):
        if self.file_image.file is not None:
            self.file.file = self.file_image.file
        elif self.file_video.file is not None:
            self.file.file = self.file_video.file
        else:
            raise ValidationError()

        super().save(*args, **kwargs)

Tags: 文件实例模型imageselfmodelsvideonot
2条回答

好的,所以我放弃了向模型中添加额外字段的最初想法,只留下了file字段,正如@schillingt所建议的那样。现在,我在clean()方法中使用自定义验证来验证文件类型

from django.db import models
from django.db.models.fields.files import ImageFieldFile
from django import forms

from custom_fields import forms as custom_forms
from custom_fields import fields as custom_fields


class MyModel(models.Model):
    file = models.ImageField()

    def clean(self):
        # Get the MIME type to have a hint of the file type
        import magic
        mime_type = magic.from_buffer(self.file.file.read(1024), mime=True)

        if mime_type.startswith('image'):
            image_field = ImageFieldFile(self, models.ImageField(),
                                         self.file.name)
            image_field.file = self.file.file
            if image_field.width:
                self.width = image_field.width
                self.height = image_field.height
                self.media_type = mime_type
            else:
                raise ValidationError({'file': forms.ImageField.
                                      default_error_messages['invalid_image']})

        elif mime_type.startswith('video'):
            video_field = custom_fields.VideoFieldFile(self,
                                                       custom_fields.VideoField(),
                                                       self.file.name)
            video_field.file = self.file.file
            if video_field.width:
                self.width = video_field.width
                self.height = video_field.height
                self.duration = video_field.duration
                self.media_type = mime_type
            else:
                raise ValidationError({'src': custom_forms.VideoField.
                                      default_error_messages['invalid_video']})

        else:
            raise ValidationError({'src': 'The file is neither an image nor a video.'})


    def save(self, *args, **kwargs):
        self.full_clean()
        super().save(*args, **kwargs)

我知道这是一个丑陋的解决方案,但这能奏效吗?我的意思是,我测试了它,它似乎起了作用,但肯定会有更好、更优雅的方式

您的模型表示数据库中的内容。我建议你不要以这种方式对抗ORM。相反,我将在创建/更新实例时使用的表单类中执行验证。使用该表单可以定义字段file_videofile_image,然后使用该字段写入file

相关问题 更多 >

    热门问题