How to Upload and Serve Images in Django Content Feed

Add the Blog and Photo Models

Our final goal is to build a feed that will contain blog posts and photos from creators that a user has subscribed to.

However, before we can do that, we need to:

  1. Add the models to hold these photo and blog posts.

  2. Provide users with the means to create the posts.

First, let's look at the models. All our changes are now concerning theblog  app, so let's add this toblog/models.py  .

          # blog/models.py from django.conf import settings from django.db import models   class Photo(models.Model):     image = models.ImageField()     caption = models.CharField(max_length=128, blank=True)     uploader = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)     date_created = models.DateTimeField(auto_now_add=True)           class Blog(models.Model):     photo = models.ForeignKey(Photo, null=True, on_delete=models.SET_NULL, blank=True)     title = models.CharField(max_length=128)     content = models.CharField(max_length=5000)     author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)     date_created = models.DateTimeField(auto_now_add=True)     starred = models.BooleanField(default=False)        

As you can see, blog posts can be optionally linked to aphoto  by theForeignKey  relationship. ThePhoto  model contains an image stored in theImageField  .

Let's make and run the migrations.

          (ENV) ~/fotoblog (master) → python manage.py makemigrations Migrations for 'blog':   blog/migrations/0001_initial.py     - Create model Photo     - Create model Blog  (ENV) ~/fotoblog (master) → python manage.py migrate Operations to perform:   Apply all migrations: admin, auth, authentication, blog, contenttypes, sessions Running migrations:   Applying blog.0001_initial... OK        

OK, now that the models are configured, let's look at handling user-uploaded images in Django.

Upload Images Using a Form

Before uploading images to Django, you need to configure where to store the media content. In this instance, media content refers to files and images that are user-uploaded.

Step 1: Configuresettings.py

To do this, you must configure two values insettings.py  .

First, theMEDIA_URL , which is the URL from which Django will attempt to serve media. In some cases, this could be a full URL to another host if you are using a third-party service to serve your media.

For this class, you're going to serve the images locally, so you can provide a path that points to your localhost server.

The second setting to configure is theMEDIA_ROOT  . It points to the directory on your machine where Django should save uploaded images.

The configuration to add is:

          # fotoblog/settings.py MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR.join_path('media/')        

Step 2: Add the Media to the URL Patterns

Now you need to update your URL patterns so that the uploaded media is accessible via a URL.

To do this, add:

          # fotoblog/urls.py from django.conf import settings from django.conf.urls.static import static  urlpatterns = [     ...     ] if settings.DEBUG:     urlpatterns += static(         settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)        

Now the images in yourMEDIA_ROOT  directory will be served at the path given byMEDIA_URL  .

Step 3: Create a Form That Can Handle Image Uploads

Now that the  settings are configured, let's add a form for uploading photos.

It's really simple to do this: you can use aModelForm , and Django will handle the file transfer and save it to the file system for you.

Let's create aforms.py  file inblog/  and add the following:

          # blog/forms.py from django import forms  from . import models  class PhotoForm(forms.ModelForm):     class Meta:         model = models.Photo         fields = ['image', 'caption']        

Step 4: Build the View to Handle Image Uploads

Now let's add the view. Usually, you only populate a form with therequest.POST  object, but as you are transferring an image, you also have to provide it with any files sent with the request. Do this by giving the argumentrequest.FILES  .

We want to set theuploader  field on thePhoto  to the user currently logged in. You can create thePhoto  object without saving it to the database by saving the form with the argumentcommit=False  . Then setuploader  to the correct value, and finally save the model to store it in the database.

          # blog/views.py from django.shortcuts import redirect, render  from . import forms  @login_required def photo_upload(request):     form = forms.PhotoForm()     if request.method == 'POST':          form = forms.PhotoForm(request.POST, request.FILES)         if form.is_valid():             photo = form.save(commit=False)             # set the uploader to the user before saving the model             photo.uploader = request.user             # now we can save             photo.save()             return redirect('home')     return render(request, 'blog/photo_upload.html', context={'form': form})        

 Uploading the image is easy as theModelForm  does all the heavy lifting!

Step 5: Add the Template

Let's add the template.

          # blog/templates/blog/photo_upload.html {% extends 'base.html' %} {% block content %}     <h2>Upload a Photo</h2>     <form method="post" enctype="multipart/form-data">         {{ form.as_p }}         {% csrf_token %}         <button type="submit" >Submit</button>     </form> {% endblock content %}        

Note how you add the attributeenctype="multipart/form-data"  to the<form>  tag. This is required for the form to handle file uploads.

Step 6: Update the URL Patterns

Now add the view to the URL patterns.

          # fotoblog/urls.py import blog.views  urlpatterns = [     ...     path('photo/upload/', blog.views.photo_upload, name='photo_upload') ]        

Step 7: Create a Feed

To see the uploaded photos, you need to fetch them in the view. Refactor thehome  view to do this.

          # blog/views.py from . import models  @login_required def home(request):     photos = models.Photo.objects.all()     return render(request, 'blog/home.html', context={'photos': photos})        

Then update the template. You can get the path of the photo from theurl  property on theimage  field. Theurl  property gets constructed from theMEDIA_URL  setting configured earlier.

          # blog/templates/blog/home.html {% extends 'base.html' %} {% block content %}     <h2>Photos</h2>     {% for photo in photos %}         <img src="{{ photo.image.url }}">         <p>{{ photo.caption }}</p>     {% endfor %} {% endblock content %}        

Great! Now let's test the new functionality.

First, upload a new photo.

Screenshot of an upload page
Screenshot of an upload page

Then check the feed.

Screenshot of feed page
Screenshot of feed page

Success! Users can now upload their photos and you can see them in the feed.

Next, you are going to add functionality that allows a user to update their profile photo.

Exercise: Upload a Profile Photo

You want to allow users to upload and display profile photos.

To do this, you are going to build a profile photo upload facility.

We have built out an updated version of the site, complete with some styling. Let's see what it looks like.

Screenshot of new styling
Screenshot of new styling

Pretty slick!

The styling is in CSS. If you want, you can take some time to style your site to your own design now. Or pull down from the GitHub repo to include the changes in your site.

You will see that your user profile is now displayed at the left of the page, with the link "Change Profile Photo" below it.

Currently, this link doesn't do anything. To make it work, you will need to:

  • Create anUploadProfilePhotoForm  form inauthentication/forms.py  - this can be aModelForm  forUser  .

  • Create a viewupload_profile_photo  in  theauthentication  app and configure the view to update the user's profile photo.

  • Create a template for this view and add the view to the URL patterns.

  • Link to the page from theChange Profile Photo  link.

  • Display the user's profile photo in the user profile if they have uploaded a profile photo; otherwise, display the default profile photo. You can check this with{% if user.profile_photo %}  .

If you get stuck:

  • Make sure you passinstance=request.user  to yourUploadProfilePhotoForm  to update the user logged in.

  • Includeenctype="multipart/form-data">  in your<form>  tag.

  • Don't forget to passrequest.FILES  toUploadProfilePhotoForm  when handling thePOST  data.

Once you are finished, check your solution against the solution in GitHub.

Let's Recap!

  • You can define theMEDIA_x  constants in the settings to dictate where Django will store user-uploaded files.

  • TheImageField  allows you to upload images to the server using aModelForm  .

Now that you can allow users to upload their own media in a view, you are ready to handle multiple forms on a single page.

fieldsdithery.blogspot.com

Source: https://openclassrooms.com/en/courses/7107341-intermediate-django/7264297-create-an-image-upload-facility

0 Response to "How to Upload and Serve Images in Django Content Feed"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel