Home > database >  How to collect an image file and save it in database
How to collect an image file and save it in database

Time:06-17

This is a project that collects inputs for name, price and image.

The major problem I am encountering is posting an image from my frontend(html) to the backend(database).

These are my codes, what is the issue

models.py

    from django.db import models
    from datetime import datetime


    class Product(models.Model):
        name = models.CharField(max_length=250)
        price = models.FloatField(default=0)
        image = models.ImageField()

forms.py

    from django import forms


    class ProductCreationForm(forms.Form):
        name = forms.CharField(label="Product Name", max_length=250, required=True)
        price = forms.DecimalField(label="Price", required=True, initial=0)
        image = forms.ImageField(label="Image", required=True, widget=forms.FileInput(attrs={'accept': "image/x-png, image/jpeg"}))

views.py

    def product_create(request):
        form = ProductCreationForm()

        if request.method == "POST":
            form = ProductCreationForm(request.POST)

            if form.is_valid():
                name = form.cleaned_data["name"]
                price = form.cleaned_data["price"]
                image = form.cleaned_data["image"]

                new_item = Product.objects.create(name=name, price=price, image=image)
                new_item.save()

            return redirect('shelf')


        else:
            return render(request, "workbench/product_create.html", {"form": form})

create.html

    <form action="", method="post">
        {% csrf_token %}

        {{ form.as_p }}
        <button type="submit" >submit</button>
    </form>

urls.py

    from django.urls import path
    from . import views


    urlpatterns = [
        path('', views.shelf, name="shelf"),
        path('/create', views.product_create, name="product-create"),
    ]

CodePudding user response:

Images are not saved in the database. they save in some storage and the path is stored in the database. I see you have not set any path to your imagefield , there should be something called the upload_to parameter.

something like this:

from django import form

class ProductCreationForm(forms.Form):
    name = forms.CharField(label="Product Name", max_length=250, required=True)
    price = forms.DecimalField(label="Price", required=True, initial=0)
    image = forms.ImageField(upload_to="projectimg/",label="Image", required=True, widget=forms.FileInput(attrs={'accept': "image/x-png, image/jpeg"}))

CodePudding user response:

When accepting files from forms, along with request.POST, you should also fetch request.FILES as well...

form = ProductCreationForm(request.POST, request.FILES)

By the way, the create(name=name, price=price, image=image) already saved the item so there's no need to call the save method new_item.save().

It would be easier to just work with a model form instead. So I'm just updating your code here...

models.py file:

class Product(models.Model):
    name = models.CharField(max_length=250)
    price = models.FloatField(default=0)
    image = models.ImageField(upload_to='image_uploads/', null=True, blank=True)

forms.py file:

from .models import Product
from django import forms
from django.utils.translation import gettext_lazy as _

class ProductCreationForm(forms.ModelForm):
    class Meta:
         model = Product
         fields = "__all__"
         labels = {
              "name": _("Product Name"), 
              "price": _("Price"), 
              "image": _("Image"),
         }
         required = (
              'name',
              'price',
              'image',
         )

Then within your view in the views.py file:

if request.method == "POST":
     form = ProductCreationForm(request.POST, request.FILES)

     if form.is_valid():
          form.save()  # This here will save the necessary data to the database
     else:
          print(form.errors)  # To show you what field(s) are causing the form not to submit

     return redirect('shelf')

Finally, the action attribute is not needed on your form tag, so you can remove it since the same function will be handling the post request.

Additionally, ensure that in your setting.py file you have something set for the MEDIA_URL and the MEDIA_ROOT

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

In your project's urls.py file:

from django.contrib import admin
from django.urls import path, include
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)
  • Related