pyborg
pyborg

Reputation: 13

How to check for uniqueness in the derived field of model in Django

I have a model like

class InfoFromFile(models.Model):
    name = models.CharField()
    title = models.CharField(max_length=200)
    date_from_file = models.DateField()
    file = models.FileField()
    file_hash = models.CharField(unique=True)

with a corresponding admin class

class InfoFromFileAdmin(admin.ModelAdmin):
    fieldsets = [
        ('Information source', {'fields': ['File']}),
    ]

    def save_model(self, request, obj, form, change):
        # custom action here to extract info from file
        # before creating and saving the model

I have a separate function for creating a hash of the file.

So, the only input field in the form is the file upload. I want to prevent duplicate files to be uploaded at all, that is, before saving the model as a part of form/model validation. If the model is attempted saved and the hash already exists, an IntegrityError is thrown.

I know about the Model.validate_unique() method, but I don't know how to apply it in the ModelAdmin.save_model(*) method.

To summarize, my question is:
How can I validate for uniqueness in a different field than the one provided by the model form? Should I make use of javascript to create the hash of the file before the admin-user hits the save button? Or make use of any other hidden fields?

EDIT: A future expansion to the site would be to allow users to upload such files (or do the same processing resulting in an output pdf-file, possibly without saving the user's file), albeit not needed now.

Upvotes: 0

Views: 456

Answers (1)

Karolis Ryselis
Karolis Ryselis

Reputation: 679

I think what you need is a custom form. You can validate whatever you want in clean_<field> method of your form. It should be similar to this:

class InfoFromFileForm(ModelForm):
    def clean_File(self):
        file_obj = self.cleaned_data['File']
        hash = get_hash() # whatever you use to get file hash
        if InfoFromFile.objects.filter(file_hash=hash).exists():
            raise ValidationError(_("The hash must be unique.")
        return file_obj

Then in your admin class

class InfoFromFileAdmin(admin.ModelAdmin):
    # your things
    form = InfoFromFileForm
    # more things

Upvotes: 1

Related Questions