2

I want to know how to upload and display the image.

I do have the classes in views.py.

class ArticleUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView): model = Article fields = ('title', 'body', 'image', 'source_url') template_name = 'article_edit.html' def test_func(self): obj = self.get_object() return obj.author == self.request.user class ArticleCreateView(LoginRequiredMixin, CreateView): model = Article template_name = 'article_new.html' fields = ('title', 'body', 'image', 'source_url') login_url = 'login' def test_func(self): obj = self.get_object() return obj.author == self.request.user def form_valid(self, form): form.instance.author = self.request.user return super().form_valid(form) 

And the relevant classes in the models.py are like as follow.

class Article(models.Model): title = models.CharField(max_length=255) body = models.TextField() date = models.DateTimeField(auto_now_add=True) image = models.ImageField( upload_to='media/', null=True, blank=True) source_url = models.URLField(blank=True, null=True, max_length=300) author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,) def __str__(self): return self.title def get_absolute_url(self): return reverse('article_detail', args=[str(self.id)]) class Comment(models.Model): article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='comments', ) comment = models.CharField(max_length=140) author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE), def __str__(self): return self.comment def get_absolute_url(self): return reverse('article_list') 

The article_list.html file is:

 {% extends 'base.html' %} {% load static %} {% block title %}Articles{% endblock title %} {% block content %} {% for article in object_list %} <div class="card"> <div class="card-header"> <span class="font-weight-bold">{{ article.title }}</span> &middot; <span class="text-muted">by {{ article.author }} | {{ article.date }}</span> </div> <div class="card-body"> {{ article.body|linebreaks}} {% comment %} {% if article.image.url|length > 0 %} <img src="{{ article.image.url }}" width="200px"> {% else %} <img src="{% static '/media/mrDoctor.jpg' %}" width="200px" /> {% endif %} {% endcomment %} <img src="{% static 'articles/mrDoctor.jpg' %}" alt="Image" width="200px" /> <a href="{{ article.source_url }}">Link</a> <a href="{% url 'article_edit' article.pk %} ">Edit</a> <a href="{% url 'article_delete' article.pk %}">Delete</a> </div> <div class="card-footer"> {% for comment in article.comments.all %} <p> <span class="font-weight-bold"> {{ comment.author }} &middot; </span> {{ comment }} </p> {% endfor %} </div> </div> <br /> {% endfor %} {% endblock content %} 

The user can select the image file from the form.

The input form I can not display the image selected from the input form shown above on the screen shot. I want to display the images dynamically, i.e., when the user choose the image file from the input form. I know I should change the part:{% static '/media/mrDoctor.jpg' %}. When I tried the commented part of article_list.html, i.e., {% if article.image.url|length > 0 %}, it did not work. I will appreciate it if you help me to fix the problem. Many thanks.

After reflecting @Hybrid suggestions, I was able to show the image on the first article but the second and the third one show only the file names.

the first article shows the image

the second and the third show only the file name

7
  • What do you mean by "what I want to do is to show the different image files selected from the folder." Commented Mar 10, 2019 at 4:37
  • In my app, I can show only one image. I want to change the image dynamically as the user selects the image. To do so, this part should be changed: <img src="{% static 'articles/mrDoctor.jpg' %}" alt="Image" width="200px" /> Commented Mar 10, 2019 at 4:39
  • How does one "select" an image? If you can explain a bit more, it will be much easier to help Commented Mar 10, 2019 at 4:43
  • The user can select the image file from the form. Commented Mar 10, 2019 at 4:48
  • @Hybrid, I attached the screen shot of my input forms. I hope it helps.Thank you for your comments. Commented Mar 10, 2019 at 4:52

1 Answer 1

4

You can do this by using JavaScript to detect when a user selects an image, and then replacing an <img /> tags src dynamically.

Example code:

<img id="image" /> <input id="files" type="file" /> <script> document.getElementById("files").onchange = function () { var reader = new FileReader(); reader.onload = function (e) { // get loaded data and render thumbnail. document.getElementById("image").src = e.target.result; }; // read the image file as a data URL. reader.readAsDataURL(this.files[0]); }; </script> 
Sign up to request clarification or add additional context in comments.

5 Comments

Somehow it works for the first article but not for the second one. I do not understand why. But it is one step closer to the solution. Should I change this.files[0]? I'll try it. Thank you.
Is the second article a separate <input />? If it is, you need to bind the JS event handler to each one. You can do this manually (copy the code for each one), or you can use JS to catch any file input, and have it match the ID of the corresponding image preview element.
Thank you, Hybrid. I thought about that too. But the problem is when the user keeps adding the articles I should manually add the <input /> as well, which is not a good approach. Any other suggestions? With many thanks.
Its hard for me to say, since you didnt include the html of adding articles. Most likely though it will be a simple trick of catching all input[name=“files”] with JS, and having them create image elements which are then appended back into the HTML
Thank you agin, Hybrid. I am lack of understanding many features of the Django yet. I will try different approach and ask your help if needed. Thank you for your kindness.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.