· 

Django: forms.py, and views.py

1. forms.py

Can you explain this code?

from django import forms

from django.core.exceptions import ValidationError

from django.core import validators

class BasicForm(forms.Form):

    title = forms.CharField(validators=[

        validators.MinLengthValidator(2, "Please enter 2 or more characters")])

    mileage = forms.IntegerField()

    purchase_date = forms.DateField()

 

Absolutely! This code defines a basic Django form class using forms.Form. Let’s break it down step by step:


📦 Imports

python
from django import forms
  • Imports Django's form classes, like Form, CharField, IntegerField, etc.

python
from django.core.exceptions import ValidationError
  • Allows you to manually raise a validation error if needed (not used in this code, but ready if you want to customize validations).

python
from django.core import validators
  • Imports built-in validation tools like MinLengthValidator.


🧾 The Form Definition

python
class BasicForm(forms.Form):
  • This defines a form class (not a model form).

  • It’s meant to be used with request.POST data from an HTML form.


🔸 Field 1: title

python
title = forms.CharField(validators=[
validators.MinLengthValidator(2, "Please enter 2 or more characters")
])
  • A text input field (like <input type="text">).

  • Must be at least 2 characters long.

  • If not, Django will show the message:

    "Please enter 2 or more characters"


🔸 Field 2: mileage

python
mileage = forms.IntegerField()
  • An input that only accepts integer values.

  • If the input isn't a valid integer, the form will show an error.


🔸 Field 3: purchase_date

python
purchase_date = forms.DateField()
  • Accepts a date in YYYY-MM-DD format by default.

  • Will show an error if the format or value is incorrect.


✅ Example HTML output

If you render {{ form.as_p }} in your template, Django will automatically generate something like:

html
<p><label for="id_title">Title:</label> <input type="text" name="title" required></p>
<p><label for="id_mileage">Mileage:</label> <input type="number" name="mileage" required></p>
<p><label for="id_purchase_date">Purchase date:</label> <input type="text" name="purchase_date" required></p>

🧪 Typical usage in a view:

python
def my_view(request):
form = BasicForm(request.POST or None)
if form.is_valid():
# Access cleaned data:
title = form.cleaned_data['title']
mileage = form.cleaned_data['mileage']
date = form.cleaned_data['purchase_date']
# Do something with the data...
return render(request, 'your_template.html', {'form': form})

 

Let me know if you want to try custom validation, add dropdowns, or turn this into a ModelForm!

 

2. a function of views.py

Can you explain the following code to me?  It is part of views.py.

def example(request) :

    form = BasicForm()

    return HttpResponse(form.as_table())

 

Certainly! Let's walk through this Django view function line by line:


python
def example(request):
  • This defines a view function named example.

  • It takes request as its argument (as all Django views do), which represents the incoming HTTP request.


python
form = BasicForm()
  • This creates a new instance of the form you previously defined: BasicForm.

  • Since no data is passed (like request.POST), this is an empty, unbound form (ready to be filled in).


python
return HttpResponse(form.as_table())
  • This returns an HTTP response to the browser.

  • form.as_table() tells Django to render the form's fields as an HTML table, with each field in its own row.


🔍 So what HTML does form.as_table() generate?

If BasicForm has these fields:

python
title = forms.CharField(...)
mileage = forms.IntegerField()
purchase_date = forms.DateField()

Then form.as_table() will produce something like this:

html
<tr><th><label for="id_title">Title:</label></th><td><input type="text" name="title" required></td></tr> <tr><th><label for="id_mileage">Mileage:</label></th><td><input type="number" name="mileage" required></td></tr> <tr><th><label for="id_purchase_date">Purchase date:</label></th><td><input type="text" name="purchase_date" required></td></tr>

⚠️ Note:

Since this view returns only the table rows (without <html>, <body>, etc.), you may want to wrap it in a proper HTML page for better presentation.


✅ Summary

This view simply:

  • Instantiates a blank BasicForm

  • Renders its fields as an HTML <table>

  • Sends that HTML back as a response

 

Would you like to also process submitted data from this form (e.g., via POST)?

 

3. form.html

Can you explain the following html code?  I don't understand onclick=... .

<p>

  <form action="" method="post">

    {% csrf_token %}

    <table>

    {{ form.as_table }}

    </table>

    <input type="submit" value="Submit">

    <input type="submit"

    onclick="window.location='{% url 'form:main' %}' ; return false;"

    value="Cancel">

  </form>

</p>

 

Great question! Let's walk through this HTML code and focus on the line with onclick.


🔍 What the code does:

This is a Django form inside a <form> tag with two buttons:

  1. Submit: Sends the form data via POST.

  2. Cancel: Doesn't send the form — instead, it redirects the user somewhere else.


⚠️ The confusing part:

html
<input type="submit"
onclick="window.location='{% url 'form:main' %}'; return false;"
value="Cancel">

Let’s break it down:


🧠 What does onclick=... mean?

  • onclick="..." is an HTML event attribute.

  • It means: "When this button is clicked, run this JavaScript code."


🔍 What is the JavaScript code?

js
window.location='{% url 'form:main' %}'; return false;
  • window.location='...' changes the browser's current page (i.e., redirects).

  • {% url 'form:main' %} is a Django template tag that returns the URL for the view named "form:main" (in the form app's urls.py).

    So, for example, it might become:

    html
    window.location='/form/';
  • return false; prevents the form from being submitted, even though the button's type is submit.


✅ So what happens when you click "Cancel"?

  • The browser does not submit the form.

  • Instead, it navigates (redirects) to the URL returned by {% url 'form:main' %} — like /form/.


✅ Summary

Button Action
Submit Submits the form data to the current page (action="") via POST
Cancel Runs JavaScript to redirect to another page (like /form/) and stops the form submission

 

Let me know if you'd like a version that uses a plain <a> link or a cleaner alternative!

 

4. a function of views.py

Can you explain the following code?  

# Call as dumpdata('GET', request.GET)

def dumpdata(place, data) :

    retval = ""

    if len(data) > 0 :

        retval += '<p>Incoming '+place+' data:<br/>\n'

        for key, value in data.items():

            retval += html.escape(key) + '=' + html.escape(value) + '</br>\n'

        retval += '</p>\n'

    return retval

 

Yes! Let's break this Python function down step by step:


🧩 Purpose of the function

The function dumpdata(place, data) is a utility for debugging:
It creates an HTML-formatted string showing the contents of a dictionary (like request.GET or request.POST), useful for displaying incoming form data.

You would call it like this:

python
dumpdata('GET', request.GET)
dumpdata('POST', request.POST)

🔍 Line by line explanation:

python
def dumpdata(place, data):
  • Defines a function named dumpdata.

  • place is just a label like "GET" or "POST" (used to show where the data came from).

  • data is expected to be a dictionary-like object, such as request.GET or request.POST.


python
retval = ""
  • Initializes an empty string that will store the result.


python
if len(data) > 0:
  • Only proceed if there is actually some data to show.


python
retval += '<p>Incoming '+place+' data:<br/>\n'
  • Adds a line like:
    <p>Incoming GET data:<br/>


python
for key, value in data.items():
retval += html.escape(key) + '=' + html.escape(value) + '</br>\n'
  • Loops through each key-value pair in the data.

  • Escapes both the key and value (for HTML safety).

  • Adds a line like:
    username=JohnDoe</br>


python
retval += '</p>\n'
  • Closes the paragraph tag.


python
return retval
  • Returns the complete HTML string.


✅ Example output (if request.GET contains {"name": "Alice", "age": "30"}):

html
<p>Incoming GET data:<br/>
name=Alice</br>
age=30</br>
</p>

💡 Why use html.escape()?

To prevent XSS attacks or display bugs if the data includes HTML-sensitive characters like <, >, or &.


 

Let me know if you'd like a version that displays the data as a table or list instead!

 

5. a class of views.py

(1)

Can you explain this?

class DumpPostView(View):  # Reusable bit...

    def post(self, request) :

        dump = dumpdata('POST', request.POST)

        ctx = {'title': 'request.POST', 'dump': dump}

        return render(request, 'form/dump.html', ctx)

 

Absolutely! This Django code defines a class-based view that handles POST requests and shows the posted data in a user-friendly way.

Let’s go through it step by step:


🔶 1. class DumpPostView(View):

  • This defines a Django class-based view named DumpPostView.

  • It inherits from View, which comes from django.views.

  • You can use it in your urls.py like this:

    python
    path('some-url/', DumpPostView.as_view(), name='some_name')

🔶 2. def post(self, request):

  • This method is automatically called when the view receives an HTTP POST request (like from a submitted form).

  • request.POST is a dictionary-like object containing all the form data that was submitted.


🔶 3. dump = dumpdata('POST', request.POST)

  • This calls a helper function named dumpdata (you defined earlier).

  • It turns the POST data into a formatted HTML string, like:

    html
    <p>Incoming POST data:<br/>
    name=Alice</br>
    age=30</br>
    </p>

🔶 4. ctx = {'title': 'request.POST', 'dump': dump}

  • This is the context dictionary that will be passed to the template.

  • title will be 'request.POST', and dump will be the formatted HTML data.


🔶 5. return render(request, 'form/dump.html', ctx)

  • This renders the template at form/dump.html with the context ctx.

  • Inside the template, you’ll probably use:

    django
    <h2>{{ title }}</h2>
    {{ dump|safe }}

    to show the POST data nicely.


✅ Summary

This view:

  1. Responds to POST requests.

  2. Extracts and formats submitted form data.

  3. Renders a template to display it.

It’s a great debugging tool for learning how forms work in Django.

 

Would you like a matching view to handle GET data too?

 

(2) 

What does {{ dump|safe }} do?  What does safe mean?

 

Great question!

🔍 What does {{ dump|safe }} mean in Django templates?

This is a template variable with a filter:

django
{{ dump|safe }}

It means:

"Render the value of the dump variable, and treat it as safe HTML, not plain text."


📌 What is the safe filter?

Django escapes HTML by default to prevent Cross-Site Scripting (XSS) attacks.

For example:

python
dump = "<p>Hello</p>"

If you do this in a template:

django
{{ dump }}

Django will escape it and display:

html
&lt;p&gt;Hello&lt;/p&gt;

But if you do:

django
{{ dump|safe }}

It tells Django:

"I trust this content — don’t escape it, render it as real HTML."

And the browser will render:

html
<p>Hello</p>

⚠️ Be careful!

Only use |safe when you're sure the content is safe (like content you've escaped yourself using html.escape()), because unescaped user input can lead to XSS vulnerabilities.


✅ In your case:

Since you're using html.escape() in dumpdata() to clean user input, it's okay to use |safe when rendering dump.


 

Would you like an example that shows the difference between {{ var }} and {{ var|safe }} side by side?

 

6. another class of views.py

What does the following code do?

class SimpleCreate(DumpPostView): 

    def get(self, request) :

        form = BasicForm()

        ctx = {'form' : form}

        return render(request, 'form/form.html', ctx)

 

Great! Let’s go step-by-step to understand what this Django class-based view does:


🔹 Code:

python
class SimpleCreate(DumpPostView):
def get(self, request):
form = BasicForm()
ctx = {'form': form}
return render(request, 'form/form.html', ctx)

 


🧠 What’s going on?

1. class SimpleCreate(DumpPostView):

  • This is a class-based view named SimpleCreate.

  • It inherits from DumpPostView, which means:

    • It gets all the behavior of DumpPostView (which you wrote earlier — it handles POST requests by dumping form data).

    • It adds support for GET requests using the get() method below.


2. def get(self, request):

This method is called when a user sends a GET request (i.e., just visits the page in their browser).


3. form = BasicForm()

  • This creates a blank instance of your form (you must have defined BasicForm somewhere earlier).

  • It’s empty and ready to be displayed for the user to fill out.


4. ctx = {'form': form}

  • A context dictionary to pass the form to the template.


5. return render(request, 'form/form.html', ctx)

  • This tells Django to render the template at form/form.html, with the form included in the context.


🔄 So What Happens Overall?

When a user visits the page (GET):

  • Django shows a blank form using form/form.html.

When a user submits the form (POST):

  • SimpleCreate doesn't define post(), so it inherits post() from DumpPostView.

  • That post() method:

    • Calls your dumpdata() function.

    • Shows the submitted form data on a page (for debugging or learning purposes).


✅ Summary:

Method What it does
get() Shows an empty form to the user
post() Processes and displays submitted form data (inherited from DumpPostView)

 

Would you like help creating the matching form/form.html template for this?

 

7. validator does not work

(1) 

I ran the whole code, and mostly it worked.   But it seems the validator doesn't work. I entered "j", only one character, in the "title" field, and pressed the submit button.  There was no error message shown, but the dump data was displayed.  Part of the code is this. Can you explain why and how can I fix it?

from django import forms

from django.core.exceptions import ValidationError

from django.core import validators

class BasicForm(forms.Form):

    title = forms.CharField(validators=[

        validators.MinLengthValidator(2, "Please enter 2 or more characters")])

    mileage = forms.IntegerField()

    purchase_date = forms.DateField()

 

You're on the right track — and you're using Django forms correctly — but the reason the validator isn't showing an error message is that you're not checking if the form is valid before displaying the data.

Let's go step-by-step:


🧠 What’s happening?

Your form has a MinLengthValidator on the title field, like so:

python
validators.MinLengthValidator(2, "Please enter 2 or more characters")

That part is correct

But in your view (probably DumpPostView.post()), you're doing this:

python
dump = dumpdata('POST', request.POST)
ctx = {'title': 'request.POST', 'dump': dump}
return render(request, 'form/dump.html', ctx)

You’re not validating the form at all, you're just dumping the raw POST data.


✅ How to fix it

You need to:

  1. Create a form instance using the POST data.

  2. Check if the form is valid.

  3. If valid → dump data.

  4. If invalid → redisplay the form with error messages.


✅ Updated post() method:

Here’s how to do it properly:

python

 

class SimpleCreate(View):

    def get(self, request):

        form = BasicForm()

        return render(request, 'form/form.html', {'form': form})

 

    def post(self, request):

        form = BasicForm(request.POST)

        if form.is_valid():

            # Form is good → dump the cleaned data

            dump = dumpdata('POST', form.cleaned_data)

            ctx = {'title': 'Valid POST Data', 'dump': dump}

            return render(request, 'form/dump.html', ctx)

        else:

            # Form has errors → show form again with error messages

            return render(request, 'form/form.html', {'form': form})

 

💡 Bonus tip: Add {{ form.errors }} in your form template

In form/form.html, make sure your template includes something like:

html
<form method="post">
{% csrf_token %}
{{ form.as_table }}
{{ form.errors }}
<input type="submit" value="Submit" />
</form>

Or better yet, Django will automatically show errors inside the form if you're using {{ form.as_p }} or {{ form.as_table }} — as long as you're passing the form back in the context after validation fails.


✅ Summary

Problem Fix
Form validators don’t show errors You're not calling form.is_valid()
How to fix Add validation logic in your view and re-render the form on failure

 

Let me know if you'd like a fully working version of the updated view + template!

 

(2) In fact, I modified `class DumpPostView(View)` as follows:

 

# Call as dumpdata('GET', request.GET)

def dumpdata(place, data) :

    retval = ""

    if len(data) > 0 :

        retval += '<p>Incoming '+place+' data:<br/>\n'

        for key, value in data.items():

            retval += html.escape(key) + '=' + html.escape(value) + '</br>\n'

        retval += '</p>\n'

    return retval

class DumpPostView(View):  # modified 

    def post(self, request) :

        form = BasicForm(request.POST)

        if form.is_valid():

        # Form is good → dump the cleaned data

            dump = dumpdata('POST', request.POST)

            ctx = {'title': 'request.POST', 'dump': dump}

            return render(request, 'form/dump.html', ctx)

        else:

        # Form has errors → show form again with error messages  

            ctx = {'form' : form}      

            return render(request, 'form/form.html', ctx)

class SimpleCreate(DumpPostView): 

    def get(self, request) :

        form = BasicForm()

        ctx = {'form' : form}

        return render(request, 'form/form.html', ctx)

 

8. SimpleUpdate() in views.py

I wrote a view for update, using old_data, which is a dummy.  Can you modify this code to refer to database and use the data there.  I am using sqlite3 as a database.

class SimpleUpdate(DumpPostView):

    def get(self, request) :

        old_data = {

            'title': 'SakaiCar', 

            'mileage' : 42, 

            'purchase_date': '2018-08-14'

        }

        form = BasicForm(old_data)

        ctx = {'form' : form}

        return render(request, 'form/form.html', ctx)

 

Great! You want to change your SimpleUpdate view so that it loads real data from your SQLite database instead of using hardcoded old_data.

Let’s assume you're using this model from earlier:

python
class Cat(models.Model):
title = models.CharField(max_length=100)
mileage = models.IntegerField()
purchase_date = models.DateField()

Here’s how you can update your view to fetch a record from the database:


✅ Updated SimpleUpdate view:

python

from django.shortcuts import get_object_or_404

from .models import Cat  # or whatever your model is

 

class SimpleUpdate(DumpPostView):

    def get(self, request):

        # Get a Cat object from the database. Use any ID you want (e.g. 1 here)

        cat = get_object_or_404(Cat, id=1)

 

        # Initialize the form with data from the model instance

        form = BasicForm(initial={

            'title': cat.title,

            'mileage': cat.mileage,

            'purchase_date': cat.purchase_date,

        })

 

        ctx = {'form': form}

        return render(request, 'form/form.html', ctx)

 

🧠 What’s happening?

  • get_object_or_404(Cat, id=1) tries to find a Cat with ID=1.

    • If it doesn't exist, it shows a 404 error.

  • We then fill the form using initial={...} with the database values.

  • You’re still using the same BasicForm.


🔁 Want to update the object on POST?

If you're also handling form submission and want to save changes, update your post() method too. Just ask if you'd like that version as well.

Let me know:

 

  • what your actual model is called

  • whether you want to support updates via POST as well
    and I’ll tailor the code more exactly!