passion
passion

Reputation: 455

how to upload the image file and display it

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

Upvotes: 2

Views: 484

Answers (1)

Hybrid
Hybrid

Reputation: 7049

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>

Upvotes: 4

Related Questions