2

I am trying to validate upload file type functionality in Django. The allowed extension would be xml only. The admin will upload a xml file and then the table would be populated with the data from xml file. The model has no filefield but the form has.

accounts/models.py --

class Coupling(models.Model):
    coupling_name = models.CharField(max_length=150, blank=False, null=True, default="")
    module_name = models.TextField(blank=False, null=True)
    def __str__(self):
        return self.coupling_name

    class Meta:
        verbose_name_plural = "Couplings"

accounts/forms.py --

class CouplingUploadForm(forms.ModelForm):

    coupling_file = forms.FileField(label='XML File Upload:', required=True)

    class Meta:
        model = models.Coupling
        exclude = ['coupling_name', 'module_name']

settings.py

UPLOAD_PATH = os.path.join(BASE_DIR, "static", "uploads")

CONTENT_TYPES = ['xml']
MAX_UPLOAD_SIZE = "2621440"

accounts/admin.py

class couplingAdmin(admin.ModelAdmin):
    list_display = ('coupling_name','module_name')
    form = CouplingUploadForm
admin.site.register(Coupling, couplingAdmin)

I have gone through some SOF references and most of them have model.FileField but in my case I do not want to save the file in model.

I tried with using magic -- https://djangosnippets.org/snippets/3039/ but I got an python-magic installation error -- Unable to find libmagic. So I would like to do it without magic.

Any help/suggestion/link is highly appreciated. Thanks in advance.

2 Answers 2

5

You can create a custom validator

def validate_file_extension(value):
    import os
    from django.core.exceptions import ValidationError
    ext = os.path.splitext(value.name)[1]
    valid_extensions = ['.xml']
    if not ext.lower() in valid_extensions:
        raise ValidationError(u'Unsupported file extension.')

Then in your form field

coupling_file = forms.FileField(label='XML File Upload:',
                               required=True, validators=[validate_file_extension])
Sign up to request clarification or add additional context in comments.

7 Comments

I think I have to add django.conf in pythonpath. Getting an error ImportError: No module named 'django.conf.settings'
Works great. Thanks a lot.
@PrithvirajMitra This link docs.djangoproject.com/en/dev/ref/validators/…would also help you if you are on Django 1.11. please upvote or accept the answer if it helped you
I am on 1.10 . What is code as parameter? To check the inside content?
@PrithvirajMitra Well validatior is kind of standard thing and you can use a single validatior function to use in multiple forms.
|
4

Simply write an clean method to your forms.py

import os 

def clean_coupling_file(self):
    file = self.cleaned_data['coupling_file']
    extension = os.path.splitext(file.name)[1]  # [0] returns path+filename
    VALID_EXTENSION = '.xml'

    if extension != VALID_EXTENSION:
        self.add_error(
            'coupling_file',
            _('Only files with ".xml" extension are supported, '
              'received: "%s" file.' % extension)
        )
    return file

2 Comments

Just because a file has a .xml extension doesn't mean that it's an XML file. You need to validate the contents as well if you want to be safe. This might happen implicitly when your code breaks later on, but it's better to be sure.
You're totally right, but I assumed, as this functionality will be for admins only, no one will try to force-break it. However, even if we allow .xml file, potential breaks should be handled at import level, not form. There's always possibility of a good file, with corrupted content, and it may not be done intentionally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.