Форма Django проверяется в консоли, но почему не в браузере? - PullRequest
1 голос
/ 02 марта 2012

Я хочу протестировать статический API Карт Google с Django 1.3 (используя Python 2.7).Для этого я создал простую форму для запроса координат (широта и долгота), уровня масштабирования и размера карты.Форма выглядит следующим образом:

from django import forms

class GoogleMapsStaticApiForm(forms.Form):
    latitude = forms.FloatField(required=True, min_value=-90.0, max_value=90.0)
    longitude = forms.FloatField(required=True, min_value=-180.0,max_value=180.0)
    zoom_level = forms.IntegerField(required=True, min_value=0, max_value=21)
    map_width = forms.IntegerField(required=True, min_value=0, max_value=640)
    map_height = forms.IntegerField(required=True, min_value=0, max_value=640)

В соответствующем представлении я хочу построить URL-адрес из информации, приведенной в форме, и вернуть URL-адрес шаблона, который должен отображать карту в том же шаблоне.

Представление:

def map_properties(request):
    map_url = 'http://maps.google.com/maps/api/staticmap?'

    if request.method == 'POST':
        form = GoogleMapsStaticApiForm(request.POST)
        if form.is_valid(): 
            center = 'center={0},{1}'.format(form.latitude, form.longitude)
            zoom = 'zoom={0}'.format(form.zoom_level)
            size = 'size={0}x{1}'.format(form.map_width, form.map_height)
            url_suffix = '&'.join((center, zoom, size, 'sensor=false'))
            map_url = ''.join((map_url, url_suffix))
    else:
        form = GoogleMapsStaticApiForm()

    return render_to_response('frontend/frontend.html', 
                          {'form':form, 'map_url':map_url},
                          context_instance=RequestContext(request))

Шаблон:

<html>
    <head>
        <title>Google Maps Static API - Demo</title>
    </head>
    <body>

        <form method="post" accept-charset="UTF-8">
            {% csrf_token %}

            {% for field in form %}
                <input type="text" placeholder={{ field.html_name }}>
            {% endfor %}
            <button type="submit">Show the fancy map!</button>
        </form>

        {% if form.is_valid %}
           <p><img src="{{ map_url }}" alt="Google Maps Static Map"></p>
        {% else %}
           <p>Form is not valid</p>
        {% endif %}

    </body>
</html>

Когда я пытаюсь проверить форму с примерами данных в консоли Django, она работает нормально:

>>> from frontend.forms import GoogleMapsStaticApiForm
>>> data = {'latitude':51.477222, 'longitude':0.0, 'zoom_level':12, 'map_width':400, 'map_height':400}
>>> f = GoogleMapsStaticApiForm(data)
>>> f.is_valid()
True

Но когда я ввожу те же данные в браузер и нажимаю кнопку отправки, тот же шаблон перезагружается, но без созданной карты.Форма никогда не подтверждается.Может кто-нибудь сказать, пожалуйста, почему это так?Большое спасибо!

Ответы [ 3 ]

3 голосов
/ 02 марта 2012

Основная проблема, с которой вы столкнулись, заключается в том, что вы решили вывести поля формы через прямой HTML, чтобы добавить атрибут placeholder, и при этом вы упустили самый важный бит - nameприписывать.Кроме того, они не будут повторно отображать существующие значения, если форма не проходит проверку.

Вместо того, чтобы делать это, следует добавить заполнитель к самим полям формы:

latitude = forms.FloatField(required=True, min_value=-90.0, max_value=90.0,
                       widget=forms.TextInput(attrs={'placeholder': 'latitude'}))

и полагаться наДжанго вывести их:

{% for field in form %}
     {{ field }}
{% endfor %}
2 голосов
/ 02 марта 2012

Похоже, что форма пуста, потому что тег ввода не содержит ни имени, ни значения атрибута :

<input type="text" class="input-small" placeholder="{{ field.html_name }}">

Чтобы браузер отправлял любые данные, тег ввода должен иметь атрибут name :

<input type="text" class="input-small" placeholder="{{ field.html_name }}" name="{{ field.html_name }}">

Чтобы на входе отображалось любое значение, на входе должен быть атрибут значения . Чтобы получить значение поля, вы должны сделать form.data['field_name'], но мы не можем сделать это в шаблоне. Итак, мы создаем шаблонный фильтр. Если вы не знаете, как это сделать, обратитесь к документации . Вот краткое руководство:

  1. Создайте subdir шаблона тегов в вашем приложении

  2. Создать пустую __init__.py в этом каталоге

  3. Создайте файл "yourapp_tags.py" в этом каталоге

Вот пример кода, который вы можете вставить в этот скрипт:

from django import template

register = template.Library()

@register.filter
def get_field_value(field):
    return field.form.data.get(field.name, '')

Затем вы можете использовать его в шаблоне для установки начального значения поля:

<input type="text" class="input-small" placeholder="{{ field.html_name }}" name="{{ field.html_name }}" value="{{ field|get_field_value }}">

Не забудьте {% load yourapp_tags %} в вашем шаблоне, иначе get_field_value не будет распознано!

0 голосов
/ 03 марта 2012

Я знаю, что на этот вопрос уже был дан ответ, но поскольку эта проблема связана с итерацией выходных данных в шаблонах, я поделился, как я отформатировал ее раньше, и у меня не было проблем с этим.

<form class="form label-inline" action="" method="post">{% csrf_token %}

    {{ form.non_field_errors }}

    {% for field in form.visible_fields %}
        <div class="field">
            {{ field.errors }}
            <label for="{{ field.auto_id }}">{{ field.label }}</label>
            {{ field }}
            {% if field.help_text %}
            <p class="field_help">{{ field.help_text }}</p>
            {% endif %}
        </div> <!-- end div.field -->
    {% endfor %}

    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}

    <input type="submit" value="Save" name="submit" />
</form>

Он охватывает ошибки, скрытые вводные данные и help_text, и он действительно полезен для настройки макета CSS и HTML.Я начал использовать это, чтобы лучше соответствовать стилю приобретенного шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...