Javascript required
Skip to content Skip to sidebar Skip to footer

Django Upload to Other Than Media Location From Admin

Django File (and Epitome) Uploads Tutorial

This tutorial shows how to implement file and and then image uploading with Django. Nosotros'll build a basic Instagram clone.

Setup

Whether you're on a Windows or Mac laptop the Desktop is a convenient place to put our lawmaking. The location doesn't matter; information technology just needs to exist easily available.

Open the control line and navigate to the Desktop. Then create a directory, insta, for our project. Nosotros will create a new virtual surroundings, activate it, and install both Django and pillow which is the Python image process library Django relies on for image files. For non-image file uploads, pillow is not needed.

                        #            Windows            >            cd            onedrive            \            desktop            \            code            >            mkdir            insta            >            cd            insta            >            python            -            m            venv            .            venv            >            .            venv            \            Scripts            \            Activate            .            ps1            (.            venv            )            >            python            -            m            pip            install            django            ~=            4            .            0            .            0            (.            venv            )            >            python            -            m            pip            install            pillow            ~=            nine            .            0            .            0            #            macOS            %            cd            ~/            desktop            /            code            %            mkdir            insta            %            cd            insta            %            python3            -            m            venv            .            venv            %            source            .            venv            /            bin            /            activate            (.            venv            )            %            python3            -            1000            pip            install            django            ~=            iv            .            0            .            0            (.            venv            )            %            python            -            1000            pip            install            pillow            ~=            9            .            0            .            0          

Now create our new Django project called django_project and a new app called posts.

                        (.venv) > django-admin startproject django_project .            (.venv) > python manage.py startapp posts          

Since we've added a new app we demand to tell Django about it at the bottom of the INSTALLED_APPS configuration in settings.py.

                        # django_project/settings.py            INSTALLED_APPS            =            [            "django.contrib.admin"            ,            "django.contrib.auth"            ,            "django.contrib.contenttypes"            ,            "django.contrib.sessions"            ,            "django.contrib.letters"            ,            "django.contrib.staticfiles"            ,            "posts"            ,            # new            ]          

Now run python manage.py drift to setup the new database for our project.

                        (.venv) > python manage.py migrate          

Models

Starting with the database model is a good choice. In our case our model Post will simply have two fields: championship and encompass. We'll as well include a __str__ method below so that the title appears in our Django admin later on.

                        # posts/models.py            from            django.db            import            models            course            Post            (            models            .            Model            ):            title            =            models            .            TextField            ()            cover            =            models            .            ImageField            (            upload_to            =            'images/'            )            def            __str__            (            self            ):            render            self            .            championship          

The location of the uploaded image will exist in MEDIA_ROOT/images. In Django, the MEDIA_ROOT setting is where we define the location of all user uploaded items. We'll fix that now.

If we wanted to use a regular file hither the only difference could be to change ImageField to FileField.

MEDIA_ROOT

Open up config/settings.py in your text editor. We will add two new configurations. By default MEDIA_URL and MEDIA_ROOT are empty and not displayed so we need to configure them:

  • MEDIA_ROOT is the accented filesystem path to the directory for user-uploaded files
  • MEDIA_URL is the URL we can use in our templates for the files
                        # config/settings.py            MEDIA_URL            =            "/media/"            MEDIA_ROOT            =            BASE_DIR            /            "media"          

Nosotros could pick a name other than media hither merely this is the Django convention. We'll also brand an images folder within it to utilize shortly.

                        (.venv) $ mkdir media            (.venv) $ mkdir media/images          

Admin

Now update the posts/admin.py file and so we can run into our Mail service app in the Django admin.

                        # posts/admin.py            from            django.contrib            import            admin            from            .models            import            Post            admin            .            site            .            register            (            Mail service            )          

And nosotros're all set! Generate a new migrations file.

                        (.venv) > python manage.py makemigrations            Migrations for 'posts':                          posts/migrations/0001_initial.py                          - Create model Post          

And so run migrate to update the database.

                        (.venv) > python manage.py migrate            Operations to perform:                          Utilise all migrations: admin, auth, contenttypes, posts, session            s            Running migrations:                          Applying posts.0001_initial... OK          

Now we tin can create a superuser business relationship to access the admin and so execute runserver to spin up the local web server for the first time.

                        (.venv) > python manage.py createsuperuser            (.venv) > python manage.py runserver          

If you become to http://127.0.0.1:8000/admin you'll be able to log in to the Django admin site. It should redirect y'all to this page:

Admin Homepage

Click on the "+ Add" link next to Posts. You tin can add whatever you like but for this tutorial I'g making a postal service on the Django Pony mascot. You tin download it here yourself if you similar.

Django Pony Post

Upon "Salvage" you will be redirected to the Posts page where nosotros can see all our posts.

Image Posts

If you look within the local media folder in your project yous'll see under images in that location is now the djangopony.png image file. See! I told you that was what MEDIA_URL would do.

Ok, so at this indicate nosotros're done with the nuts. But let'southward take it a footstep further and display our posts which ways urls.py, views.py, and template files.

URLs

The confusing thing most Django is that you oft need 4 dissimilar merely interconnected files for one webpage: models.py, urls.py, views.py, and a template html file. I find it easiest to reason virtually this by going in order from models -> urls -> views -> template files. Our model is already washed so that means diving into URL routes.

We'll need 2 urls.py file updates. Outset at the project-level config/urls.py files we demand to add imports for settings, include, and static. And then ascertain a route for the posts app. Note we also demand to add the MEDIA_URL if settings are in DEBUG mode, otherwise we won't be able to view uploaded images locally.

                        # config/urls.py            from            django.contrib            import            admin            from            django.conf            import            settings            # new            from            django.urls            import            path            ,            include            # new            from            django.conf.urls.static            import            static            # new            urlpatterns            =            [            path            (            "admin/"            ,            admin            .            site            .            urls            ),            path            (            ""            ,            include            (            "posts.urls"            )),            # new            ]            if            settings            .            DEBUG            :            # new            urlpatterns            +=            static            (            settings            .            MEDIA_URL            ,            document_root            =            settings            .            MEDIA_ROOT            )          

Next nosotros'll need to sort out the URL routes within the posts app. Offset create that new file in your text editor posts/urls.py. Then nosotros'll put all posts on the homepage so again use the empty string "" every bit our route path.

                        # posts/urls.py            from            django.urls            import            path            from            .views            import            HomePageView            urlpatterns            =            [            path            (            ""            ,            HomePageView            .            as_view            (),            name            =            "dwelling house"            ),            ]          

This references a view chosen HomePageView which we'll create adjacent.

Views

We tin apply the generic class-based ListView hither, import our Post model, so create a HomePageView that uses the model and a template called home.html.

                        # posts/views.py            from            django.views.generic            import            ListView            from            .models            import            Post            class            HomePageView            (            ListView            ):            model            =            Post            template_name            =            "domicile.html"          

Boom! Moving on the last step is that template file called home.html.

Templates

We take two choices for our template's location. We could put it within the posts app at posts/templates/posts/home.html but I observe that structure redundant. Plus it's harder to reason about templates when they are all cached within their corresponding apps. So typically I volition instead create a project-level templates directory.

                        (.venv) > mkdir templates          

We tell Django to also look here for any templates past updating the TEMPLATES configuration within config/settings.py.

                        # config/settings.py            TEMPLATES            =            [            {            ...            "DIRS"            :            [            BASE_DIR            /            "templates"            ],            # new            ...            },            ]          

Then create a template file inside this directory, templates/domicile.html, that volition display the title and image for all posts. But similar Instagram would :)

                        <!-- templates/abode.html -->            <            h1            >Django Prototype Uploading</            h1            >            <            ul            >            {% for post in object_list %}            <            h2            >{{ post.title }}</            h2            >            <            img            src            =            "{{ post.comprehend.url}}"            alt            =            "{{ post.title }}"            >            {% endfor %}            </            ul            >          

Ok, that's information technology! Brand sure the server is running with the python manage.py runserver command and navigate to our homepage at http://127.0.0.1:8000. Refresh the folio if needed.

Homepage

And voila! If you add additional posts with a title and epitome via the admin they will appear on the homepage.

Course

Now we can add a form so regular users, who wouldn't have access to the admin, can also add posts. That ways creating a new page with a class.

Let'due south start with the views.py file. Nosotros'll proper name our new view CreatePostView which will extend the built-in Django CreateView. We'll also import reverse_lazy to handle the redirect back to our homepage afterward the form has been submitted.

Within the view nosotros specify the model, a form_class which we'll create next, the template_name, and finally a success_url which is what we want to happen after submission.

                        # posts/views.py            from            django.views.generic            import            ListView            ,            CreateView            # new            from            django.urls            import            reverse_lazy            # new            from            .forms            import            PostForm            # new            from            .models            import            Post            class            HomePageView            (            ListView            ):            model            =            Post            template_name            =            "domicile.html"            class            CreatePostView            (            CreateView            ):            # new            model            =            Postal service            form_class            =            PostForm            template_name            =            "post.html"            success_url            =            reverse_lazy            (            "home"            )          

Next up that course. Commencement create it in your text editor at posts/forms.py. Then nosotros can extend Django'south congenital-in ModelForm. All nosotros need for our basic form is to specify the correct model Mail and the fields we want displayed which are title and cover.

                        # posts/forms.py            from            django            import            forms            from            .models            import            Post            class            PostForm            (            forms            .            ModelForm            ):            course            Meta            :            model            =            Post            fields            =            [            "championship"            ,            "cover"            ]          

We'll make a defended page for this form at the path of post/.

                        # posts/urls.py            from            django.urls            import            path            from            .views            import            HomePageView            ,            CreatePostView            # new            urlpatterns            =            [            path            (            ""            ,            HomePageView            .            as_view            (),            proper noun            =            "domicile"            ),            path            (            "post/"            ,            CreatePostView            .            as_view            (),            name            =            "add_post"            )            # new            ]          

Then create the new template at templates/mail service.html. And fill it with a headline and class. It's important to always add csrf_token for protection. We're specifying grade.as_p which means Django volition output each field every bit a paragraph tag.

                        <!-- templates/post.html -->            <            h1            >Create Mail Folio</            h1            >            <            form            method            =            "post"            enctype            =            "multipart/form-data"            >            {% csrf_token %}   {{ form.as_p }}            <            button            type            =            "submit"            >Submit New Post</            push button            >            </            course            >          

That's it! Make sure your server is running and get to the page at http://127.0.0.i:8000/post/.

Create Post

After you submit a new post you'll be redirected back to the homepage and will see all the posts.

Side by side Steps

Hosting this site in product would require a few additional steps. Notably, information technology's likely that you lot would apply WhiteNoise on the server for your static files, notwithstanding WhiteNoise explicitly does not support media files. The common practice is to apply django-storages for this purpose and connect to something like S3.

What else? You lot probably want to put restrictions around the paradigm size which tin can be done initially in the models.py file or with CSS. Perhaps you want to add together edit and delete options as well for the Mail. And yous'll probable want a thumbnail version of the images too which can be done with sorl-thumbnail.

israelwassed.blogspot.com

Source: https://learndjango.com/tutorials/django-file-and-image-uploads-tutorial