Як відобразити значення поля форми Django у шаблоні?


80

У мене є форма з властивістю електронної пошти.

При використанні {{ form.email }}у разі помилки перевірки, Django все одно відображає попереднє значення в атрибуті значення вхідного тегу:

<input type="text" id="id_email" maxlength="75" class="required"
       value="some@email.com" name="email">

Я хочу зробити вхідний тег сам (щоб додати код JavaScript і клас помилки на випадок помилки). Наприклад, це мій шаблон замість {{ form.email }}:

<input type="text" autocomplete="on" id="id_email" name="email"
       class="email {% if form.email.errors %} error {% endif %}">

Однак це не відображає помилкового значення ( some@email.comу цьому прикладі) для користувача.

Як отримати значення поля в шаблоні?


Документація містить кілька корисних прикладів для роботи з шаблонами форм.
djvg

Відповіді:


130

Це був запит на функцію, який було виправлено в Django 1.3.

Ось помилка: https://code.djangoproject.com/ticket/10427

В основному, якщо ви запускаєте щось після 1.3, у шаблонах Django ви можете зробити:

{{ form.field.value|default_if_none:"" }}

Або в Jinja2:

{{ form.field.value()|default("") }}

Зверніть увагу, що field.value()це метод, але в Django шаблони ()опущено, тоді як у методі Jinja2 виклики явні.

Якщо ви хочете знати, яку версію Django ви використовуєте, вона повідомить вам, коли ви виконаєте команду runserver.

Якщо у вас щось було до версії 1.3, ви, ймовірно, можете скористатися виправленням, розміщеним у вищевказаній помилці: https://code.djangoproject.com/ticket/10427#comment:24


Це правильна відповідь для Django> = 1.3. Це помітно відсутнє в документації django, але це, схоже, виправлено (принаймні у версії розробника). code.djangoproject.com/ticket/16851
zlovelady

19
Це має неприємний ефект, якщо form.field.valueє None, то не буде доступний широкому текст «None». Щоб натомість відобразити порожній рядок, використовуйте{{ form.field.value|default_if_none:"" }}
cberzan

+1 за згадку про це працює лише в> = 1.3. Я все ще працюю на версії 1.2 і не міг зрозуміти, чому це не спрацювало, поки не прочитав це.
Wipqozn

Робота з {{ form.initial.fieldname }}цим (Django 1.2.3).
santiagopim

1
Я можу помилитися @santiagopim, але я вважаю, що це дасть вам початкове значення кожного разу, замість того, щоб надавати вам значення, яке вводить користувач. Наприклад, зробіть форму, яка замість того, щоб надсилати повідомлення, видає помилку, і ви побачите, що вхід користувача перейшов до початкового значення після подання, а не зберігає введення користувача.
mlissner

42

Ви можете зробити це з шаблону приблизно таким чином:

{% if form.instance.some_field %}
      {{form.instance.some_field}}
{% else %}
      {{form.data.some_field}}
{% endif %}

Це відобразить значення екземпляра (якщо форма створена з екземпляром, ви можете використовувати замість цього початковий, якщо хочете), або ж відобразити дані POST, наприклад, коли виникає помилка перевірки.


2
ганьба, що ця відповідь закопана так глибоко! Це спосіб зробити це без додавання коду до вашого проекту або виправлення вашого django.
w

2
Чи можете ви розширити те, що я заповнюю, на ці складені поля? Я спробував кілька варіантів, і це не спрацювало.
jordaninternets

17

Здається, це працює.

{{ form.fields.email.initial }}

11
Можливо, я помиляюся, але я вважаю, що це буде показувати початкове значення кожного разу. Наприклад, спробуйте надіслати форму, щоб вона видала помилку, і ви побачите, що форма, яка перезавантажується, показуючи помилку, знову матиме початкове значення, а не значення, яке ввів користувач до того, як він викинув помилку.
mlissner

16

У мене є просте рішення для вас!

{{ form.data.email }}

Я спробував це, і це спрацювало. Для цього потрібно, щоб ваш подання заповнив клас форми даними POST.

Дуже простий приклад:

def your_view(request):
  if request.method == 'POST':
    form = YourForm(request.POST)
    if form.is_valid():
      # some code here
  else:
    form = YourForm()

  return render_to_response('template.html', {'form':form})

Сподіваюся, це вам допоможе. Якщо у вас є якісь запитання, повідомте мене.


Очищені дані не містять поля електронної пошти, якщо їх не вдалося очистити під час перевірки.
shanyu

Ти правий. Ви не зможете отримати доступ до очищених даних, якщо is_valid () не вдасться. Шукаю іншого рішення.
Йенс,

Я оновив свій код. Було просте рішення. Замість clean_data просто використовуйте дані. Це спрацювало, навіть якщо перевірка не вдається!
Йенс,

дані у мене не працюють ... {{form.description}} дає елемент керування з правильним значенням {{form.data.description}} порожній (насправді {{form.data}} повертає {})
Eran Kampf

До речі, я ініціалізую форму, виконавши: form_details = forms.UserDetailsForm (instance = request.user)
Еран Кампф


5

Рішення, запропоноване Йенсом, є правильним. Однак виявляється, що якщо ви ініціалізуєте ModelForm екземпляром (приклад нижче), django не заповнить дані:

def your_view(request):   
    if request.method == 'POST':
        form = UserDetailsForm(request.POST)
        if form.is_valid():
          # some code here   
        else:
          form = UserDetailsForm(instance=request.user)

Отже, я створив власний базовий клас ModelForm, який заповнює вихідні дані:

from django import forms 
class BaseModelForm(forms.ModelForm):
    """
    Subclass of `forms.ModelForm` that makes sure the initial values
    are present in the form data, so you don't have to send all old values
    for the form to actually validate.
    """
    def merge_from_initial(self):
        filt = lambda v: v not in self.data.keys()
        for field in filter(filt, getattr(self.Meta, 'fields', ())):
            self.data[field] = self.initial.get(field, None)

Тоді простий приклад вигляду виглядає так:

def your_view(request):   if request.method == 'POST':
    form = UserDetailsForm(request.POST)
    if form.is_valid():
      # some code here   
    else:
      form = UserDetailsForm(instance=request.user)
      form.merge_from_initial()

Я не розумію, чому django за замовчуванням не робить цього ... Я думаю, що я надішлю виправлення і подивлюся, що люди про це говорять.
Еран Кампф

3

Я спробував кілька із згаданих можливостей, і ось як я вирішив свою проблему:

#forms.py
class EditProfileForm(forms.ModelForm):
    first_name = forms.CharField(label='First Name',
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    last_name = forms.CharField(label='Last Name',
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    # username = forms.CharField(widget=forms.TextInput(
    #                              attrs={'class': 'form-control'}),
    #                              required=True)
    address = forms.CharField(max_length=255, widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    phoneNumber = forms.CharField(max_length=11,
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    photo = forms.ImageField(label='Change Profile Image', required=False)

    class Meta:
        model = User
        fields = ['photo', 'first_name', 'last_name', 'phoneNumber', 'address']
                  # 'username',



#views.py
def edit_user_profile(request, username):
    user = request.user
    username = User.objects.get(username=username)
    user_extended_photo = UserExtended.objects.get(user=user.id)
    form = EditProfileForm(request.POST or None, request.FILES, instance=user)
    user_extended = UserExtended.objects.get(user=user)
    if request.method == 'POST':
        if form.is_valid():
            # photo = UserExtended(photo=request.FILES['photo'] or None, )
            user.first_name = request.POST['first_name']
            user.last_name = request.POST['last_name']
            user_extended.address = request.POST['address']
            user_extended.phoneNumber = request.POST['phoneNumber']
            user_extended.photo = form.cleaned_data["photo"]
            # username = request.POST['username']
            user_extended.save()
            user.save()

            context = {
                'form': form,
                'username': username,
                'user_extended_photo': user_extended_photo,
            }

            return render(request, 'accounts/profile_updated.html', context)
    else:
        photo = user_extended.photo
        first_name = user.first_name
        last_name = user.last_name
        address = user_extended.address
        phoneNumber = user_extended.phoneNumber
        form = EditProfileForm(
            initial={'first_name': first_name, 'last_name': last_name,
                                   'address': address, 'phoneNumber': phoneNumber,
                                   'photo': photo})
    context = {
        'form': form,
        'username': username,
        'user_extended_photo': user_extended_photo,

    }
    return render_to_response('accounts/edit_profile.html', context,
                                 context_instance=RequestContext(request))

#edit_profile.html
  <form action="/accounts/{{ user.username }}/edit_profile/" method="post" enctype='multipart/form-data'>
                                    {% csrf_token %}
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                {{ form.as_p }}
                                            </div>
                                        </div>
                                    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
                                    <button type="submit"  value="Update Profile" class="btn btn-info btn-fill pull-right">Update Profile</button>
                                    <div class="clearfix"></div>
                                </form>

Я намагаюся пояснити це таким чином, щоб новачкам було легше зрозуміти. Зверніть пильну увагу наelse:

        photo = user_extended.photo
        first_name = user.first_name
        last_name = user.last_name
        address = user_extended.address
        phoneNumber = user_extended.phoneNumber
        form = EditProfileForm(
            initial={'first_name': first_name, 'last_name': last_name,
                                  'address': address, 'phoneNumber': phoneNumber,
                                  'photo': photo}) 

Це те, що отримує атрибут значення, наприклад:

<p><label for="id_first_name">First Name:</label> <input class="form-control" id="id_first_name" name="first_name" type="text" value="Emmanuel" /></p>
<p><label for="id_last_name">Last Name:</label> <input class="form-control" id="id_last_name" name="last_name" type="text" value="Castor" /></p>

2

Якщо ви заповнили форму екземпляром, а не даними POST (як вимагає запропонована відповідь), ви можете отримати доступ до даних за допомогою {{form.instance.my_field_name}}.


2

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

{% if form.email.data %} {{ form.email.data }}
{% else %} {{ form.initial.email }} 
{% endif %}

Наведені вище рішення не працювали для мене дуже добре, і я сумніваюся, що вони працювали б у випадку з префіксом форм (таких як майстри та набори форм). Рішення, які використовуються, {{ form.data.email }}не можуть працювати, оскільки це пошук словника, і з префіксними формами ваше ім’я поля виглядатиме приблизно так: '1-email' (майстер та префікс) або 'form-1-email' (набір форм), і знак мінус (-) заборонений у пунктирних виразах пошуку шаблону.

{{form.field_name.value}} є лише Django 1.3+.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.