Upload file to database with file link

I am working on a project whereby the user has to upload a document. I have successfully been able to upload a file to the database and serve the user the uploaded file. I however want to upload files to the database using the file link rather than just selecting file from your device.

models.py

class Books(models.Model):
    title = models.CharField(max_length=500, default="")
    author = models.CharField(max_length=500, default="")
    publication = models.CharField(max_length=500, default="")
    edition = models.IntegerField(default="")
    is_available = models.BooleanField()
    book = models.FileField(
        default="",
        upload_to="books",
        validators=[validate_book_extension],
        verbose_name="books",
    )
    genre = models.ForeignKey(Genre, on_delete=models.CASCADE, default="")

    class Meta:
        verbose_name_plural = "Books"

    def __str__(self):
        return self.title

views.py

def books(request):
    genres_names = Genre.objects.all()
    if request.method == "POST":
        form = BookFile(request.POST, request.FILES)
        files = request.FILES.getlist("book")
        genres_name = request.POST.get("genres")
        try:
            if form.is_valid():
                new_old_genre, created = Genre.objects.get_or_create(
                    genres=genres_name.lower()
                )
                genre = Genre.objects.filter(genres=genres_name)
                if files:
                    for f in files:
                        names = str(f)
                        name = names.strip(".pdf")
                        Books.objects.create(
                            genre=new_old_genre, book_title=name, book=f
                        )
                return redirect(index)
        except IntegrityError:
            messages.error(request, "value exist in database")
            return redirect(books)
    else:
        form = BookFile()
    return render(request, "books.html", {"form": form, "genres_names": genres_names})

forms.py

class BookInfo(forms.ModelForm):
    class Meta:
        model = Genre
        fields = [
            "genres",
        ]
        widgets = {"genres": forms.TextInput(attrs={"list": "genres"})}


class BookFile(BookInfo):
    book = forms.FileField(widget=forms.ClearableFileInput(attrs={"multiple": True}))

    class Meta(BookInfo.Meta):
        fields = BookInfo.Meta.fields + [
            "book",
        ]

HTML template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload Books</title>
</head>
<body>
    <form action="/books/" method="POST" enctype='multipart/form-data'>
        {% csrf_token %}
        {% if request.user.is_authenticated %}
            
            <p>
                {{form.book}}
            </p>

            <p>
                {{form.genres}}
                <datalist id="genres">
                    <select name="" id="">
                        {% for name in genres_names %}
                        <option value="{{name.genres}}">{{name.genres}}</option>
                        {% endfor %}
                    </select>
                </datalist>
            </p>

            <p>
                <input type="submit" value="Create">
            </p>

            <div>
                <a href="/signout/"><input type="button" value="SignOut"></a>
            </div>
            
            <p>
                {{form.errors}}
            </p>

            {% for message in messages %}
                <p>{{ message }}</p>
            {% endfor %}
        {% endif %}
    </form>
</body>
</html>

So please how do I go about it

Actually, Django does just that. It takes the file and uploads it to the specified directory in your models. In your case, that is books/. Afterward, it uploads the file path (link) to the database.

You can modify Queryset dictionary values like this...

models.py

class DEMOClass(models.Model):
      field1 = models.CharField(max_length=255, null=True,blank=True)
      field2 = models.ImageField(upload_to='Images')

      def __str__(self):
            return self.field1

views.py

def InsertData(request):
    data = DEMOClass.objects.values('field1','field2')
    print('------ Before ------')
    print(data)        
    for i in data:
        i.update({'field2':str(request.build_absolute_uri(i['field2']))})
    print('------ After ------')
    print(data) 

Output

------ Before ------
<QuerySet [{'field1': 'test', 'field2': 'Images/download_rBWYYCh.jpg'}]>
------ After ------
<QuerySet [{'field1': 'test', 'field2': 'http://127.0.0.1:8000/Images/download_rBWYYCh.jpg'}]>
Back to Top