File upload error in Django

Hello,

I'm trying to figure out why I'm having problems with file upload in Django... I made sure to create the directory and also made sure it has the appropriate permissions. This is working on my local machine; but failing with "Bad Request (400)" when I'm running it on OpenShift. I did get it working once, but it stopped working after that and I can't figure it out; I would greatly appreciate a second set of eyes.

The File module code:
from django.db import models
from django.dispatch import receiver
from BAGCA.settings import MEDIA_ROOT_FILES

class Files(models.Model):
    class Meta:
        verbose_name_plural = "Files"

    def __str__(self):
        return u'%s' % self.filename

    filename = models.CharField(max_length=100)
    file = models.FileField(upload_to=MEDIA_ROOT_FILES)


# These two auto-delete files from filesystem when they are unneeded:
@receiver(models.signals.post_delete, sender=Files)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `Files` object is deleted.
    """
    if instance.file:
        if os.path.isfile(instance.file.path):
            os.remove(instance.file.path)


@receiver(models.signals.pre_save, sender=Files)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """Deletes file from filesystem
    when corresponding `Files` object is changed.
    """
    if not instance.pk:
        return False

    try:
        old_file = Files.objects.get(pk=instance.pk).file

        if not old_file:
            return False
    except Files.DoesNotExist:
        return False

    new_file = instance.file
    if not old_file == new_file:
        if os.path.isfile(old_file.path):
            os.remove(old_file.path)

Open in new window


Variables in the settings file:
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'media')
MEDIA_ROOT_FILES = os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'USER_UPLOADED_FILES')
MEDIA_URL = '/media/'

Open in new window


Value of $OPENSHIFT_DATA_DIR:
echo $OPENSHIFT_DATA_DIR
/var/lib/openshift/5521fe5afcf9334c7600019a/app-root/data/

Output of the makemigrations command:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Files',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('filename', models.CharField(max_length=200)),
                ('file', models.FileField(upload_to=b'/var/lib/openshift/5521fe5afcf9334c7600019a/app-root/data/')),
            ],
            options={
            },
            bases=(models.Model,),
        ),
    ]

Open in new window


I've been working at this for a while, and I can't figure out why this isn't working... I would greatly appreciate any information in resolving this error.
Errang GenevreAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gelonidaCommented:
do you get any error message?

you could enable debugging  in DJango's settings.py
DEBUG=True
and see whether you get any error message on your browser.

Something else to consider.

Is the file, that you try to upload huge?
perhaps your web server  /  Openshift have a maximum upload size that is exceeded by your upload attempt.
Can  you upload big files with a non Python Openshift application?
0
Errang GenevreAuthor Commented:
Even with DEBUG = True in settings.py; I just get the "bad request" error. Looking into why that is.

And my files are a few kb; nothing gigantic
0
Errang GenevreAuthor Commented:
Hm... I think I've been following an outdated tutorial.

It told me to start a "Python" cartridge on OpenShift; and run Django through there.

But, OpenShift now has a "Django" cartridge; includes a nice demo; started a "file_upload" module there and I'm able to upload files.

Doesn't actually solve the problem; but this is a better alternative.

I am still curious why the file upload didn't work in a Python environment...
0
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Errang GenevreAuthor Commented:
This is ridiculous... when I integrate the "File Upload" module with the rest of the application; it stops working...

I'm using the same file path, and everything...

This method works:

def create_quiz_form(request):
    if request.method == 'POST':
        form = UploadQuizData(request.POST, request.FILES)
        if form.is_valid():

            filename = "temporary_file.txt"
            fd = open('%s/%s' % (MEDIA_ROOT_FILES, filename), 'wb')

            group = request.POST['group_choices']
            quiz_name = request.POST['quiz_name']
            trainer = request.POST['trainer']
            quiz_description = request.POST['quiz_description']
            course_code = request.POST['course_code']
            due_date = request.POST['due_date']
            duration_hours = request.POST['duration_hours']
            required_score = request.POST['required_score']

            determine_if_quiz_exists = Quiz.objects.filter(quiz_name=quiz_name)

            if not determine_if_quiz_exists:
                create_quiz = Quiz(quiz_name=quiz_name,
                                   quiz_description=quiz_description,
                                   trainer=trainer,
                                   course_code=course_code,
                                   due_date=due_date,
                                   duration_hours=duration_hours,
                                   required_score=required_score)
                create_quiz.save()
                create_quiz.groups.add(group)
                quiz_id = Quiz.objects.get(quiz_name=quiz_name)

                for line in request.FILES['file'].read():
                    fd.write(line)

                fd.close()

                written_file = open(MEDIA_ROOT_FILES + '/temporary_file.txt', 'r')

                for line in written_file:
                    parts = re.split(r'\t', line)

                    create_question = Question(quiz=quiz_id, question_text=parts[0])
                    create_question.save()
                    for part_counter in range(1, len(parts)):
                        is_answer = False
                        parts[part_counter] = parts[part_counter].strip()
                        if parts[part_counter][0] == '(' and \
                                        parts[part_counter][len(parts[part_counter]) - 1] == ')':
                            parts[part_counter] = parts[part_counter][1:len(parts[part_counter]) - 1]
                            is_answer = True

                        create_choice = Choice(question=Question.objects.get(pk=create_question.id),
                                               choice_text=parts[part_counter].strip(), answer=is_answer)
                        create_choice.save()

                fd.close()
                os.remove(MEDIA_ROOT_FILES + '/temporary_file.txt')
                form = UploadQuizData()
                data = {'form': form}
                return render(request, 'create_quiz_form.html', data)

    else:
        form = UploadQuizData()

    data = {'form': form}
    return render(request, 'create_quiz_form.html', data)

Open in new window


This method:
- Reads in a file from a file input form
- Writes the file to a directory on the system
- Reads the file back in and inserts data into a database
- Deletes the file

Its a little crazy that my method works; but Django's built in functionality fails...

I know better than to place the blame on Django; but I can't figure out what's going on.
0
Errang GenevreAuthor Commented:
I looked around and finally figured out what the problem was; Django has a security measure to write anything outside of the current project's directory (or so I gathered from what I read).

I finally found this: https://docs.djangoproject.com/en/1.8/topics/files/

from django.db import models
from django.core.files.storage import FileSystemStorage

fs = FileSystemStorage(location='/media/photos')

class Car(models.Model):
    ...
    photo = models.ImageField(storage=fs)

Open in new window


I was missing the lines that refer to the FileSystemStorage module. Worked like a charm soon as I put those lines in.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gelonidaCommented:
Glad you found it.
It is still strange, that you found nowhere trace logfiles etc. to indicate this.


True in my personal projects all my data was below MEDIA_ROOT, that's why I never enncountered this issue
0
Errang GenevreAuthor Commented:
Yea, there was a python.log file; but all it had was an entry that a 400 response has been sent.

And yea, I didn't want to put it under MEDIA_ROOT because it was under version control and didn't want the files to be overwritten.
0
gelonidaCommented:
ah I see.
In my projects mediaroot was always empty.
What you could do (not sure it makes sense for ypour project)
have your version controlled files in one directory and either copy (or symlink) them during server installation.
0
Errang GenevreAuthor Commented:
These are user upload files; and they would also have to be able to delete it.

I would have to potentially save 100s of files, and restore them; and also integrate Django's file storage with git.
0
Errang GenevreAuthor Commented:
I didn't receive a response from anyone else.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Python

From novice to tech pro — start learning today.