1

I am new to django and tried to fix this problem, but couldn't find whats wrong with it. All the validations of forms are passed perfectly, but the image doesn't actually get uploaded to the media root. I tried to show images and I only get image icon instead of Image.

settings root part:

STATIC_ROOT = os.path.join(BASE_DIR, 'Vote','static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

models code:

class Vote(models.Model):
    name = models.CharField(max_length=50)
    image = models.ImageField(upload_to= "images/vote/")
    rating = models.IntegerField(default=0)
    vote_type = models.ForeignKey(VoteType)

    def __unicode__(self):
        return self.name

views.py create(view) code:

def create(request):
    class RequiredFormSet(BaseFormSet):
        def __init__(self, *args, **kwargs):
            super(RequiredFormSet, self).__init__(*args, **kwargs)
            for form in self.forms:
                form.empty_permitted = False
    VoteFormSet = formset_factory(VoteForm, max_num=10, formset=RequiredFormSet)
    if request.method == 'POST': # If the form has been submitted...
        vote_list_form = VoteTypeForm(request.POST) # A form bound to the POST data
        vote_list_form.pub_date = timezone.now()
        # Create a formset from the submitted data
        vote_item_formset = VoteFormSet(request.POST, request.FILES)
        if vote_list_form.is_valid() and vote_item_formset.is_valid():
            vote_list = vote_list_form.save()
            for form in vote_item_formset.forms:
                vote_item = form.save(commit=False)
                vote_item.vote_type = vote_list
                print vote_item.vote_type
                vote_item.save()
            return HttpResponseRedirect('created/%s' %vote_list.id) # Redirect to a 'success' page
    else:
        vote_list_form = VoteTypeForm()
        vote_item_formset = VoteFormSet()
        vote_list_form.pub_date = timezone.now()

    c = {'vote_form': vote_list_form,
         'vote_item_formset': vote_item_formset,
        }
    c.update(csrf(request))

    return render_to_response('Vote/create.html', c)

and there also is template code (which is pretty huge and not sure if it is required):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
{% load staticfiles %}
    <link rel="stylesheet" type="text/css" href="{% static 'Vote/style.css' %}" />
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Dynamic Forms in Django Example</title>


<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>

<script type="text/javascript">
$(document).ready(function() {
  // Code adapted from http://djangosnippets.org/snippets/1389/
  function updateElementIndex(el, prefix, ndx) {
    var id_regex = new RegExp('(' + prefix + '-\\d+-)');
    var replacement = prefix + '-' + ndx + '-';
    if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
 replacement));
    if (el.id) el.id = el.id.replace(id_regex, replacement);
    if (el.name) el.name = el.name.replace(id_regex, replacement);
  }
  function deleteForm(btn, prefix) {
    var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
    if (formCount > 1) {
      // Delete the item/form
      $(btn).parents('.item').remove();
      var forms = $('.item'); // Get all the forms
      // Update the total number of forms (1 less than before)
      $('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
      var i = 0;
      // Go through the forms and set their indices, names and IDs
      for (formCount = forms.length; i < formCount; i++) {
        $(forms.get(i)).children().children().each(function() {
          updateElementIndex(this, prefix, i);
        });
      }
    } // End if
    else {
        alert("You have to enter at least one todo item!");
    }
    return false;
  }
  function addForm(btn, prefix) {
    var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
    // You can only submit a maximum of 10 todo items 
    if (formCount < 10) {
      // Clone a form (without event handlers) from the first form
      var row = $(".item:first").clone(false).get(0);
      // Insert it after the last form
      $(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);

      // Remove the bits we don't want in the new row/form
      // e.g. error messages
      $(".errorlist", row).remove();
      $(row).children().removeClass('error');

      // Relabel/rename all the relevant bits
      $(row).children().children().each(function() {
        updateElementIndex(this, prefix, formCount);
        if ( $(this).attr('type') == 'text' )
          $(this).val('');
      });

      // Add an event handler for the delete item/form link 
      $(row).find('.delete').click(function() {
        return deleteForm(this, prefix);
      });
      // Update the total form count
      $('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1); 
    } // End if
    else {
      alert("Sorry, you can only enter a maximum of ten items.");
    }
    return false;
  }
  // Register the click event handlers
  $("#add").click(function() {
    return addForm(this, 'form');
  });

  $(".delete").click(function() {
    return deleteForm(this, 'form');
  });
});
</script>

</head>
<body>

<h1>Dynamic Forms in Django Example</h1>
<h2>Todo List</h2>

<form action="" method="POST" enctype="multipart/form-data">{% csrf_token %}
    <div class="section">
        {{ vote_form.as_p }}
    </div>

    <h2>Todo Items</h2>
    {{ vote_item_formset.management_form }}
    {% for form in vote_item_formset.forms %}
    <div class="item">
      {{ form.as_p }}
      <p style=""><a class="delete" href="#">Delete</a></p>
    </div>
    {% endfor %}

    <p><a id="add" href="#">Add another item</a></p>

    <input type="submit" value=" Submit " />

</form>

</body>
</html>

enter image description here When I create a file with create view, it doesn't upload an image to the media/images/vote. Why is this happening?

EDIT 1:added some code Someone also told me that I should add this to my code

 if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
    )

The Problem now is that the When I try to get Image, the program looks for images at:

"GET /Vote/216/voting/images/vote/background_OeAkutY.gif/ HTTP/1.1" 404 3135

Which I think he takes from my urls.py file. But I dont get why is the program looking in /Vote/ID/voting... instead of MEDIA_ROOT. Or does GET not mean that it is looking at that place?

This is my Vote/urls.py:

urlpatterns = [
    #url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^$', views.index, name='index'),
    url(r'^(?P<pk>[0-9]+)/results/$', views.results, name='results'),
    url(r'^(?P<pk>[0-9]+)/voting/$', views.voting, name='voting'),
    url(r'^create/$', views.create, name='create'),
    url(r'^create/created/(?P<pk>[0-9]+)/$', views.created, name='created'),
]
GreedyAi
  • 2,709
  • 4
  • 29
  • 55

4 Answers4

4

You are confused between media and static. Hopefully this will clarify the matter:

Static Files

Static files are files that are shipped as part of your application.

STATIC_ROOT is where the collectstatic command will dump all static files, so you can move them to the production web server.

You don't need to mess with STATIC_ROOT during development.


In your case, you have an application Vote, and inside it you have a static folder. That's all you need to serve static files during development. All you have to do is {% static 'folder/filename.ext' %} where folder is the folder inside static that contains your file.

So if your directory structure is:

/Vote
 - __init__.py
 - migrations
 - admin.py
 - views.py
 - static
   - vote
     - images
       - foo.jpg

You need <img src="{% static 'vote/images/foo.jpg' %}">

Media Files

Media files are what django calls files that are uploaded by your application's users

For uploading files, you need to set a location where all uploaded files are stored. This location is the parent directory and its universal across your entire project. The setting for this is MEDIA_ROOT. This should be a full system file path.

Suppose you set MEDIA_ROOT = '/home/foo/bar/proj/media', and in your models you have:

image = models.ImageField(upload_to='logos/')

Files for the model will be uploaded to /home/foo/bar/proj/media/logos/.

To display these files, you need to tell django the name of a link that points to the MEDIA_ROOT directory, this setting is MEDIA_URL.

For development, you need to do three things:

  1. Set MEDIA_URL to /media/

  2. Configure urls.py to serve media files:

    urlpatterns = [
        # ... the rest of your URLconf goes here ...
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    
  3. Add 'django.template.context_processors.media' to context_processors in TEMPLATES. This will activate {{ MEDIA_URL }} in your templates.

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • Hey can you say a bit more about last part? part 3. I don't really understand what you mean there. Other than that thx for great answer – GreedyAi Jul 15 '15 at 13:46
  • I added the code in settings.py, but the images still don't appear on the webpage :( – GreedyAi Jul 15 '15 at 13:57
0

from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'', include('blog.urls')),

   ]

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

gaurav_kamble
  • 300
  • 1
  • 4
  • 8
  • No I haven't added that. Where exactly should I add it? and where should I import static from? I just tried this and got error static() got an unexpected keyword argument 'document_root' – GreedyAi Jul 15 '15 at 12:55
  • Hey can you comment on my answer? the problem was in MEDIA_ROOT, but the web-page still doesn't show the images. – GreedyAi Jul 15 '15 at 13:08
0

I found the problem was in my settings code.

Here is the fixed code:

STATIC_ROOT = os.path.join(BASE_DIR, 'Vote','static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR,STATIC_ROOT,'media')
MEDIA_URL = '/media/'

now it is uploading to the correct folder, but It is not showing it on webpage, cause it is looking in a wrong location. -_- Anyways thx for help!

When I am trying to check the image it does:

"GET /Vote/216/voting/images/vote/background_OeAkutY.gif/ HTTP/1.1" 404 3135

but I don't get why is it looking for image in Vote/id-num/voting/images/vote/ rather than the media root. Or is this just url and I am wrong somewhere else? would appretiate comments on that. Thanks

GreedyAi
  • 2,709
  • 4
  • 29
  • 55
0

Change your MEDIA_ROOT according to the path of your media files:
For eg. C:\Users\Vato\PycharmProjects\Project3\Vote\media

gaurav_kamble
  • 300
  • 1
  • 4
  • 8