On my app, I can add new courses from Django Admin Panel Only by using the model in Django Admin Panel.
Picture 1 - Django Admin Panel
Picture 2 - Adding New Course from Admin Panel
I want to automate this whole process. I want to create a form where users can fill out the form and submit their Course using UI. And That course will automatically be added to the Courses. So, to achieve my goal, what are the necessary steps I should take? For a better understanding of my problem here is the GitHub repo link to my project.
GitHub Repo of My Project
Tecah.html form for adding new Course:
{% extends 'layouts/base.html' %}
{% load static %}
{% load humanize %}
{% block content %}
<div >
<br>
<h1>Teach on Hogwarts</h1>
<br>
{% if user.is_authenticated %}
<h3 align="center">
<i ></i>
Welcome
<i ></i>
</h3><br>
<img src="{% static 'images/info_banner.png' %}" alt="info" width="770" height="200" style="vertical-align:middle;margin:auto auto"/>
<br>
<div >
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div >
<label for="formGroupExampleInput" >Course Title</label>
<input name="title" type="text" id="f1" placeholder="Enter the course title" required>
</div>
<div >
<label>CATEGORY</label>
<select name="category" id="f2" required>
<option value="GD">Graphis & Design</option>
<option value="WD">Web & Mobile Development</option>
<option value="BE">Basic Education</option>
<option value="CS">Computer Science</option>
<option value="PT">Programming & Tech</option>
</select>
</div>
<div >
<label for="formGroupExampleInput2" >Short Description</label>
<input name="short_description" required type="text" id="f3" placeholder="Write a short Description">
</div>
<div >
<label for="exampleFormControlTextarea1" >Description</label>
<textarea name="description" id="f4" rows="3" required></textarea>
</div>
<div >
<label for="formGroupExampleInput2" >Outcome</label>
<input name="outcome" type="text" id="f5" placeholder="">
</div>
<div >
<label for="formGroupExampleInput2" >Requirements</label>
<input name="requirements" type="text" id="f6" placeholder="Write about prerequisites">
</div>
<div >
<label for="formGroupExampleInput2" >Language</label>
<input name="language" type="text" required id="f7" placeholder="Which Language is used for this course?">
</div>
<div >
<label>PRICE ($)</label>
<input type="number" id="f8" required value="19.99" name="price">
</div>
<div >
<label for="formGroupExampleInput2" >Level</label>
<input name="level" type="text" id="f9" placeholder="Difficulty of this course?">
</div>
<div >
<label for="formGroupExampleInput2" >Video URL</label>
<input name="url" type="text" required id="f10" placeholder="Enter the URL of this course.">
</div>
<div >
<label>Thumbnail</label>
<input type="file" required name="photo">
</div>
<button type="submit" >Submit</button>
</form>
</div>
{% else %}
<p align="center">
<i align="center"></i><br>
Please login first to access this feature!!!
</p><br>
{% endif %}
<br>
</div>
{% endblock %}
Forms.py (I created this manually):
from django import forms
from django.contrib.auth import authenticate
from django.contrib.auth.forms import UserCreationForm
from .models import Category,Course,Lesson
Models.py:
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models
from django.utils.text import slugify
from django.utils.timezone import now
from accounts.models import User
class Category(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField(max_length=200, unique=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Category, self).save(*args, **kwargs)
class Course(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
slug = models.SlugField(max_length=200, unique=True, primary_key=True, auto_created=False)
short_description = models.TextField(blank=False, max_length=60)
description = models.TextField(blank=False)
outcome = models.CharField(max_length=200)
requirements = models.CharField(max_length=200)
language = models.CharField(max_length=200)
price = models.FloatField(validators=[MinValueValidator(9.99)])
level = models.CharField(max_length=20)
thumbnail = models.ImageField(upload_to='thumbnails/')
video_url = models.CharField(max_length=100)
is_published = models.BooleanField(default=True)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Course, self).save(*args, **kwargs)
class Lesson(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='lessons')
title = models.CharField(max_length=100)
duration = models.FloatField(validators=[MinValueValidator(0.30), MaxValueValidator(30.00)])
video_url = models.CharField(max_length=100)
created_at = models.DateTimeField(default=now)
updated_at = models.DateTimeField(default=now)
def __str__(self):
return self.title
urls.py:
from django.urls import path
from .views import *
app_name = 'courses'
urlpatterns = [
path('courses/<slug:slug>', CourseDetailView.as_view(), name='course-details'),
path('courses/<slug:slug>/category', CoursesByCategoryListView.as_view(), name='course-by-category'),
]
CodePudding user response:
You should use ModelForm
, in the following way for saving the Course
model instances.
tecah.html
{% extends 'layouts/base.html' %}
{% load static %}
{% load humanize %}
{% block internalStyle %}
<style>
.green{
color:green;
font-size:1.2rem;
}
</style>
{% endblock internalStyle %}
{% block content %}
<div >
<br>
<h1>Teach on Hogwarts</h1>
<br>
{% if messages %}
<ul >
{% for message in messages %}
<li{% if message.tags %} {% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% if user.is_authenticated %}
<h3 align="center">
<i ></i>
Welcome
<i ></i>
</h3><br>
<img src="{% static 'images/info_banner.png' %}" alt="info" width="770" height="200" style="vertical-align:middle;margin:auto auto"/>
<br>
<div >
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Save">
</form>
</div>
{% else %}
<p align="center">
<i align="center"></i><br>
Please login first to access this feature!!!
</p><br>
{% endif %}
<br>
</div>
{% endblock %}
forms.py
from django import forms
from .models import Course
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ['title', 'category', 'short_description', 'description', 'video_url',
'outcome', 'requirements', 'language', 'price', 'level', 'thumbnail']
views.py
from django.http import Http404
from django.shortcuts import render
from django.views.generic import DetailView, ListView
from django.shortcuts import redirect
from django.contrib import messages
from cart.cart import Cart
from courses.models import Course, Category
from udemy.models import Enroll
from .forms import CourseForm
def add_courses(request):
if request.method == 'POST':
form = CourseForm(request.POST, request.FILES)
if form.is_valid():
title = form.cleaned_data['title']
category = form.cleaned_data['category']
print('------------------------------------------')
print(category)
print('------------------------------------------')
short_descrip = form.cleaned_data['short_description']
descrip = form.cleaned_data['description']
outcome = form.cleaned_data['outcome']
require = form.cleaned_data['requirements']
lang = form.cleaned_data['language']
pr = form.cleaned_data['price']
level = form.cleaned_data['level']
url = form.cleaned_data['video_url']
photo = form.cleaned_data['thumbnail']
course_instance = Course(title=title, user=request.user, category=category, short_description=short_descrip,
description=descrip, outcome=outcome, requirements=require, language=lang, price=pr, level=level, video_url=url, thumbnail=photo)
course_instance.save()
messages.success(
request, f'{course_instance}The course has been added successfully.', 'green')
return redirect('courses:add_courses')
else:
form = CourseForm()
return render(request, 'courses/tecah.html', {'form': form})
Add a block internalStyle
in layouts/base.html
.
layouts/base.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hogwarts</title>
{% block internalStyle %}
{% endblock internalStyle %}
{% include 'partials/header.html' %}
</head>
<body >
{% include 'partials/navbar.html' %}
{% block content %}{% endblock %}
{% include 'partials/footer.html' %}
{% include 'partials/scripts.html' %}
</body>
</html>