1

I'm trying the Tango With Django Tutorial and the overwrite in the clean() method isn't working to add 'http://' in my urls. What is wrong in this code?

forms.py

class PageForm(forms.ModelForm):

    ...

    def clean(self):
        cleaned_data = self.cleaned_data
        url = cleaned_data.get('url')

        if url and not url.startswith('http://'):
            url += 'http://'
            cleaned_data['url'] = url

        return cleaned_data

views.py

def add_page(request, category_name_slug):

    try:
        cat = Category.objects.get(slug=category_name_slug)
    except Category.DoesNotExist:
        cat = None

    if request.method == 'POST':
        form = PageForm(request.POST)
        if form.is_valid():
            if cat:
                page = form.save(commit=False)
                page.category = cat
                page.views = 0
                page.save()
                return category(request, category_name_slug)
        else:
            print(form.errors)
    else:
        form = PageForm()

    context_dict = {'category': cat, 'form': form}

    return render(request, 'rango/add_page.html', context_dict)

add_page.html

{% extends "base.html" %}

{% block title %}Add Page{% endblock title %}

{% block content %}
    <h1>Add a Page</h1>
    <form id='page_form' method='post' action="">
        {% csrf_token %}
        {% for hidden in form.hidden_fields %}
            {{ hidden }}
        {% endfor %}

        {% for field in form.visible_fields %}
            {{ field.errors }}
            {{ field.help_text }}
            {{ field }}
        {% endfor %}
        <input type="submit" name="submit" Value="Create Page" />
    </form>
{% endblock content %}

The admin is working properly, but the html itself isn't accepting this writing.

ArrowsX
  • 505
  • 1
  • 4
  • 9
  • @kaveman> can you insert a breakpoint at the beginning of `clean()` and check the content of `self.cleaned_data` and `self.errors`? I bet the url's not in the former, but the error message already is in the latter. – spectras Jun 30 '15 at 00:00

2 Answers2

1

Usually, since you are cleaning only one field, you should do this in a field-specific method clean_url.

def clean_url(self):
    url = self.cleaned_data['url']
    # your cleaning here
    return url
Mischback
  • 843
  • 5
  • 18
  • Should I still overwrite the clean method? And how do I call it in views.py? – ArrowsX Jun 29 '15 at 20:33
  • 2
    Just add the outlined clean_url() instead oft your original clean(). As a rule: Cleaning, that only addresses one field should go into a field specific method, cleaning that involves more than one field into clean(). When you call is_valid(), form validation is triggered. – Mischback Jun 29 '15 at 20:37
0

you need this:

def clean(self):
    cleaned_data = super(PageForm, self).clean() # <-----------
    url = cleaned_data.get('url')
    if url and not url.startswith('http://'):
        url += 'http://'
        cleaned_data['url'] = url
    return cleaned_data
doniyor
  • 36,596
  • 57
  • 175
  • 260
  • It still doesn't work, when I try adding an URL like 'www.google.com', it still gives me the message 'Please enter a URL' – ArrowsX Jun 29 '15 at 20:08
  • @ArrowsX if you are using an url field on model level it will validate and give you the form validation error to add 'http://' to be a valid url. As for overriding the complete clean method just to validate one field is not very django like rather use clean_url(self) – Pieter Hamman Jun 29 '15 at 20:25
  • @doniyor `ModelForm.clean()` just enables uniqueness validation and returns `self.cleaned_data`. Although it is right it ought to be called, it won't fix this issue. – spectras Jun 29 '15 at 23:56