忽略迁移中的 Django 模型字段

时间:2021-02-21 20:34:57

标签: python django django-models

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

  • fileFileField 字段。这只会用于在数据库中有 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)

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

好的,所以我放弃了向模型添加额外字段的最初想法,我只留下了 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)

我知道这是一个丑陋的解决方案,但这可行吗?我的意思是,我测试了它,它似乎有效,但肯定会有更好、更优雅的方法。

相关问题