Як відобразити значення поля форми 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.