Django: Làm cách nào để thêm các thuộc tính html tùy ý vào các trường đầu vào trên một biểu mẫu?


101

Tôi có một trường đầu vào được hiển thị với một mẫu như sau:

<div class="field">
   {{ form.city }}
</div>

Được hiển thị dưới dạng:

<div class="field">
    <input id="id_city" type="text" name="city" maxlength="100" />
</div>

Bây giờ, giả sử tôi muốn thêm một autocomplete="off"thuộc tính vào phần tử đầu vào được hiển thị, tôi sẽ làm điều đó như thế nào? Hoặc onclick="xyz()"hoặc class="my-special-css-class"?

Câu trả lời:


126

Kiểm tra trang này

city = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))

2
Ok, cảm ơn bạn. Trong trường hợp của tôi, tôi đang sử dụng ModelForm vì vậy tôi không xác định rõ ràng các trường biểu mẫu (ví dụ: lớp AddressForm (form.ModelForm): class Meta: model = models.Address) Điều này có nghĩa là tôi không thể sử dụng ModelForm hoặc có điều gì đó đặc biệt. cần làm?
Người dùng


1
@InfinifinityLoopy bên trong init cho biểu mẫu, bạn có thể thêm một số mã để lấy trường và sửa đổi các thuộc tính widget của nó. Đây là một số tôi đã sử dụng trước đó để sửa đổi 3 trường: `` cho field_name trong ['image', 'image_small', 'image_mobile']: field = self.fields.get (field_name) field.widget.attrs ['data- file '] =' file '' '
Stuart Axon

4
Còn các thuộc tính không nhận các đối số như "bắt buộc" và "tự động lấy nét" thì sao?
Wilhelm Klopp

1
Giải pháp này là không tốt vì không có sự phân tách các mối quan tâm. Các thuộc tính HTML không được viết bằng mã python IMO. Giải pháp Mikhail Korobov là ưu việt.
David D.

115

Xin lỗi vì quảng cáo, nhưng gần đây tôi đã phát hành một ứng dụng ( https://github.com/kmike/django-widget-tweaks ) giúp các tác vụ như vậy trở nên ít khó khăn hơn để các nhà thiết kế có thể làm điều đó mà không cần chạm vào mã python:

{% load widget_tweaks %}
...
<div class="field">
   {{ form.city|attr:"autocomplete:off"|add_class:"my_css_class" }}
</div>

Hay cách khác,

{% load widget_tweaks %}
...
<div class="field">
   {% render_field form.city autocomplete="off" class+="my_css_class" %}
</div>

3
Ứng dụng tuyệt vời Mike, đúng như những gì tôi đang tìm kiếm!
jmagnusson

tài liệu không yêu cầu bạn thêm "widget_tweaks" vào ứng dụng đã cài đặt của bạn trong cài đặt, có thể đáng để đưa điều đó vào tài liệu.
James Lin

Xin chào James, nó không được nhấn mạnh nhưng trong phần 'Cài đặt' đã có ghi chú về việc thêm 'widget_tweaks' vào INSTALLED_APPS.
Mikhail Korobov

@MikhailKorobov cảm ơn bạn rất nhiều vì ứng dụng này, nó đã giúp tôi rất nhiều! Đây đúng là thứ tôi đang tìm kiếm. Tôi cần một biểu mẫu từ ModelForm và không muốn chèn thủ công các thuộc tính này vào từng trường đơn lẻ (40 trong số chúng), vì vậy tôi đã quản lý một cách trang nhã để đạt được kết quả tương tự trong vài giây :) Đây phải là câu trả lời được chấp nhận!
Ljubisa Livac

Tôi đã định viết đơn như vậy. Nhờ tiết kiệm công sức của tôi.
Anuj TBE

31

Nếu bạn đang sử dụng "ModelForm":

class YourModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(YourModelForm, self).__init__(*args, **kwargs)
        self.fields['city'].widget.attrs.update({
            'autocomplete': 'off'
        })

3
Tốt! Không cần phải xác định rõ ràng tất cả các widget bây giờ.
Mikael Lindlöf

20

Nếu bạn đang sử dụng ModelForm, ngoài khả năng sử dụng __init__như @Artificioo được cung cấp trong câu trả lời của anh ấy, có một widgetstừ điển trong Meta cho vấn đề đó:

class AuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title', 'birth_date')
        widgets = {
            'name': Textarea(attrs={'cols': 80, 'rows': 20}),
        }

Tài liệu liên quan


1
Cố gắng tìm ra lý do tại sao này có upvotes ít hơn câu trả lời ở trên ... đôi khi tôi nghĩ rằng các nhà phát triển Django / Python chỉ thích cách khó làm việc ...
trpt4him

@ trpt4him Sử dụng phương pháp init rất hữu ích để tạo Mixin hoặc Lớp cơ sở mà bạn có thể sử dụng lại trong các Biểu mẫu khác. Đây là điển hình trong một dự án quy mô vừa đến lớn. Meta.widgets rất tốt cho một Biểu mẫu duy nhất. Vì vậy, cả hai đều là câu trả lời tốt.
Akhorus

2

Tôi không muốn sử dụng toàn bộ một ứng dụng cho việc này. Thay vào đó, tôi tìm thấy mã sau đây ở đây https://blog.joeymasip.com/how-to-add-attributes-to-form-widgets-in-django-templates/

# utils.py
from django.template import Library
register = Library()

@register.filter(name='add_attr')
def add_attr(field, css):
    attrs = {}
    definition = css.split(',')

    for d in definition:
        if ':' not in d:
            attrs['class'] = d
        else:
            key, val = d.split(':')
            attrs[key] = val

    return field.as_widget(attrs=attrs)

sử dụng thẻ trong tệp html

{% load utils %}
{{ form.field_1|add_attr:"class:my_class1 my_class2" }}
{{ form.field_2|add_attr:"class:my_class1 my_class2,autocomplete:off" }}

0

Giao diện và kết xuất biểu mẫu cuối cùngTôi đã dành khá nhiều ngày để cố gắng tạo các mẫu biểu mẫu có thể sử dụng lại để tạo và cập nhật các mô hình trong biểu mẫu Django. Lưu ý rằng đang sử dụng ModelForm để thay đổi hoặc tạo đối tượng. Tôi cũng đang sử dụng bootstrap để tạo kiểu cho các biểu mẫu của tôi. Tôi đã sử dụng django_form_tweaks cho một số biểu mẫu trước đây, nhưng tôi cần một số tùy chỉnh mà không phụ thuộc nhiều vào mẫu. Vì tôi đã có jQuery trong Dự án của mình nên tôi quyết định tận dụng các thuộc tính của nó để tạo kiểu cho các biểu mẫu của tôi. Đây là mã và có thể hoạt động với bất kỳ hình thức nào.

#forms.py
from django import forms
from user.models import User, UserProfile
from .models import Task, Transaction

class AddTransactionForm(forms.ModelForm):
    class Meta:
       model = Transaction
       exclude = ['ref_number',]
       required_css_class = 'required'

Views.py

@method_decorator(login_required, name='dispatch')
class TransactionView(View):
def get(self, *args, **kwargs):
    transactions = Transaction.objects.all()
    form = AddTransactionForm
    template = 'pages/transaction.html'
    context = {
        'active': 'transaction',
        'transactions': transactions,
        'form': form
    }
    return render(self.request, template, context)

def post(self, *args, **kwargs):
    form = AddTransactionForm(self.request.POST or None)
    if form.is_valid():
        form.save()
        messages.success(self.request, 'New Transaction recorded succesfully')
        return redirect('dashboard:transaction')
    messages.error(self.request, 'Fill the form')
    return redirect('dashboard:transaction')

Lưu ý về mã HTML : Đang sử dụng phương thức bootstrap4 để loại bỏ những rắc rối khi tạo nhiều chế độ xem. Có lẽ tốt hơn nên sử dụng CreateView hoặc UpdateView chung. Liên kết Bootstrap và jqQery

 <div class="modal-body">
    <form method="post" class="md-form" action="." enctype="multipart/form-data">
      {% csrf_token %}
      {% for field in form %}
      <div class="row">
        <div class="col-md-12">
          <div class="form-group row">
            <label for="" class="col-sm-4 col-form-label {% if field.field.required %}
            required font-weight-bolder text-danger{%endif %}">{{field.label}}</label>
            <div class="col-sm-8">
              {{field}}
            </div>

          </div>
        </div>
      </div>

      {% endfor %}

      <input type="submit" value="Add Transaction" class="btn btn-primary">
    </form>
  </div>

Mã Javascript hãy nhớ tải điều này trong $(document).ready(function() { /* ... */});chức năng.

var $list = $("#django_form :input[type='text']");
$list.each(function () {
    $(this).addClass('form-control')
  });
  var $select = $("#django_form select");
  $select.each(function () {
    $(this).addClass('custom-select w-90')
  });
  var $list = $("#django_form :input[type='number']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
  var $list = $("form :input[type='text']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
  var $select = $("form select");
  $select.each(function () {
    $(this).addClass('custom-select w-90')
  });
  var $list = $("form :input[type='number']");
  $list.each(function () {
    $(this).addClass('form-control')
  });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.