Django Form vs HTML form

Hello,

What is the difference between model based or normal Django form and normal html form for being used in CRUD?
By normal HTML form I mean just get the HTML form fields by name and values in the request.POST.get and then using it for Create/update with the help of {% csrf_token %}.
I mean is it wrong or OK?

Thank you.

An html form is only what is rendered in the browser. A Django form is a lot more than that. The Working with forms page covers this in a lot more detail, and does a better job than what I could do here.

<opinion>
I would go on to say that I consider it very wrong. The facilities provided by the Django forms consists of a lot of features that you should be doing (or must do) when processing form input. (This includes things like validating fields, checking form integrity, performing data type conversions, etc.)

You can either write the code yourself to do all that - in which case I’d be asking why you’re even bothering to use Django at all, or you can use Django as designed and intended.
</opinion>

Hello,

I do that because when I use a bootstrap theme for the front-end it has beautiful style and if I use the HTML form fields names & values with request.POST.get in my views.py then the style of the front-end will stay the same as it was designed for all the screen sizes, … .
So I wanted to know that if it was ok then I will do the same in my project.

Here I copied a piece of the code from the related .py files for you to check:

Hello Ken,

Thanks for the explanation. Here is example that I am talking about.

sm_app.Models.py :

Overriding the Default Django Auth User and adding One More Field (user_type)

class CustomUser(AbstractUser):
“”“Django data model CustomUser”""
user_type_data = ((1, ‘HOD’), (2, ‘Teacher’), (3, ‘Student’), (4, ‘Parent’), (5, ‘Staff’))
user_type = models.CharField(default=1, choices=user_type_data, max_length=10)

class Parent(models.Model):
“”“Django data model Admin”""
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Staff(models.Model):
“”“Django data model Admin”""
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class AdminHOD(models.Model):
“”“Django data model Admin”""
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Teacher(models.Model):
“”“Django data model Teacher”""
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
address = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Course(models.Model):
“”“Django data model Course”""
course_name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

# def __str__(self):
#     return str(self.course_name)

class Subject(models.Model):
“”“Django data model Subject”""
course_id = models.ForeignKey(Course, on_delete=models.CASCADE)
teacher_id = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
subject_name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

# def __str__(self):
#     return str(self.subject_name)

class Student(models.Model):
“”“Django data model Student”""
admin = models.OneToOneField(CustomUser, on_delete=models.CASCADE, blank=True, null=True)
gender = models.CharField(max_length=100)
profile_pic = models.ImageField(upload_to=“SM_app/students”)
address = models.TextField()
course_id = models.ForeignKey(Course, on_delete=models.DO_NOTHING)
session_start_year = models.DateField(blank=True, null=True)
session_end_year = models.DateField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

# def __str__(self):
#     return str(self.admin.first_name)

.
.
.

Part of sm_app.urls.py :

path('add_student/', HoDViews.add_student, name='add_student'),
path('add_student_save/', HoDViews.add_student_save, name='add_student_save'),
path('edit_student/<str:student_id>/', HoDViews.edit_student, name='edit_student'), 
path('edit_student_save/', HoDViews.edit_student_save, name='edit_student_save'),

.
.
.

Part of views.py :

def add_student(request):
courses = Course.objects.all()
context = {‘courses’: courses}
return render(request, ‘hod_template/add_student_template.html’, context)

def add_student_save(request):
if request.method != ‘POST’:
return HttpResponse(‘Method Not Allowed’)
else:
first_name = request.POST.get(‘first_name’)
last_name = request.POST.get(‘last_name’)
username = request.POST.get(‘username’)
email = request.POST.get(‘email’)
password = request.POST.get(‘password’)
address = request.POST.get(‘address’)
session_start = request.POST.get(‘session_start’)
session_end = request.POST.get(‘session_end’)
course_id = request.POST.get(‘course’)
gender = request.POST.get(‘gender’)

    try:
        # Manager methods¶ ==> https://docs.djangoproject.com/en/3.2/ref/contrib/auth/  -  create_user is a method already defined in django.contrib.auth AbstractUser model and objects is the model manager here.
        user = CustomUser.objects.create_user(username=username, password=password, email=email,
                                              first_name=first_name, last_name=last_name, user_type=3)
        user.student.address = address
        course_obj = Course.objects.get(id=course_id)
        user.student.course_id = course_obj
        user.student.session_start_year = session_start
        user.student.session_end_year = session_end
        user.student.gender = gender
        user.student.profile_pic = ''
        user.save()
        messages.success(request, 'Successfully added the Student.')
        return HttpResponseRedirect('/add_student')
    except:
        messages.error(request, 'Failed to add the Student.')
        return HttpResponseRedirect('/add_student')

def manage_student(request):
students = Student.objects.all()
context = {‘students’: students}
return render(request, ‘hod_template/manage_student_template.html’, context)

def edit_student(request, student_id): # This student_id is actually student.admin.id
courses = Course.objects.all()
student = Student.objects.get(admin=student_id)
context = {‘courses’: courses, ‘student’: student}
return render(request, ‘hod_template/edit_student_template.html’, context)

def edit_student_save(request):
if request.method != ‘POST’:
return HttpResponse(’

Method is not allowed!

')
else:
student_id = request.POST.get(‘student_id’)
first_name = request.POST.get(‘first_name’)
last_name = request.POST.get(‘last_name’)
username = request.POST.get(‘username’)
email = request.POST.get(‘email’)
address = request.POST.get(‘address’)
session_start = request.POST.get(‘session_start’)
session_end = request.POST.get(‘session_end’)
course_id = request.POST.get(‘course’)
gender = request.POST.get(‘gender’)
try:
user = CustomUser.objects.get(id=student_id)
user.first_name = first_name
user.last_name = last_name
user.username = username
user.email = email
user.save()

        student = Student.objects.get(admin=student_id)
        student.address = address
        student.session_start_year = session_start
        student.session_end_year = session_end
        student.gender = gender

        course = Course.objects.get(id=course_id)
        student.course_id = course
        student.save()
        messages.success(request, 'Successfully Edited Student.')
        return HttpResponseRedirect('/edit_student/' + student_id)
    except:
        messages.error(request, 'Failed to Edit Student!')
        return HttpResponseRedirect('/edit_student/' + student_id)

.
.
.

edit_student_save.html :

          <form role="form" action="{% url 'sm_app:edit_student_save' %}" method="post">
              {% csrf_token %}
            <div class="card-body">
              <div class="form-group">
                <label >Email address</label>
                <input type="email" class="form-control" placeholder="Enter email" name="email" value="{{ student.admin.email }}">
              </div>
              <div class="form-group">
                <label >First Name</label>
                <input type="text" class="form-control" placeholder="First Name" name="first_name" value="{{ student.admin.first_name }}">
              </div>
              <div class="form-group">
                <label >Last Name</label>
                <input type="text" class="form-control" placeholder="Last Name" name="last_name" value="{{ student.admin.last_name }}">
              </div>
              <div class="form-group">
                <label >Username</label>
                <input type="text" class="form-control" placeholder="Username" name="username" value="{{ student.admin.username }}">
                <input type="text" hidden name="student_id" value="{{ student.admin.id }}">
              </div>
              <div class="form-group">
                <label >Address</label>
                <input type="text" class="form-control" placeholder="Username" name="address" value="{{ student.address }}">
              </div>
              <div class="form-group">
                <label >Course</label>
                  <select class="form-control" name="course">
                    {% for course in courses %}
                        <!--  If the condition is satisfied then the option is selected  -->
                        <option value="{{ course.id }}"  {% if course.id == student.course_id.id  %} selected {% endif %}>{{ course.course_name }}</option>
                    {% endfor %}
                  </select>
              </div>
              <div class="form-group">
                  <label>Gender</label>
                  <select class="form-control" name="gender">
                      <option value="" {% if student.gender == 'Male' %} selected {% endif %}>Male</option>
                      <option value="" {% if student.gender == 'Female' %} selected {% endif %}>Female</option>
                  </select>
              </div>
              <div class="form-group">
                  <label>Session Start</label>
                  <input type="date" class="form-control" placeholder="Session Start Year" name="session_start" value="{{ student.session_start_year|date:'Y-m-d' }}">
              </div>
              <div class="form-group">
                  <label>Session End</label>
                  <input type="date" class="form-control" placeholder="Session End Year" name="session_end" value="{{ student.session_end_year|date:'Y-m-d' }}">
              </div>
              <div class="form-group">
                  {% if messages %}
                      {% for message in messages %}
                          {% if message.tags == 'error' %}
                          <div class="alert alert-danger" style="margin-top: 10px;">{{ message }} </div>
                          {% endif %}
                          {% if message.tags == 'success' %}
                          <div class="alert alert-success" style="margin-top: 10px;">{{ message }} </div>
                          {% endif %}
                      {% endfor %}
                  {% endif %}
                  <!-- /.col -->
              </div>

            </div>
            <!-- /.card-body -->

            <div class="card-footer">
              <button type="submit" class="btn btn-primary btn-block">Update Student</button>
            </div>
          </form>

.
.
.

Thanks.

When posting code here, please enclose it between line of three backtick - ` characters. That ensures the code stays properly formatted.

Also, you can specify the css classes to be used in form fields - both for model forms and non-model forms. Hand-crafting the html provides no benefits.

If you’ve got a specific question as to how to handle something, please trim your code down to the smallest sample demonstrating the issue.

Noted.

Thank you very much.