Làm cách nào để thêm trình giữ chỗ trên CharField trong Django?


195

Lấy hình thức rất đơn giản này làm ví dụ:

class SearchForm(Form):
    q = forms.CharField(label='search')

Điều này được kết xuất trong mẫu:

<input type="text" name="q" id="id_q" />

Tuy nhiên, tôi muốn thêm placeholderthuộc tính vào trường này với giá trị Searchđể HTML sẽ trông giống như:

<input type="text" name="q" id="id_q" placeholder="Search" />

Tốt nhất là tôi muốn chuyển giá trị giữ chỗ vào CharFieldtrong lớp biểu mẫu thông qua một từ điển hoặc đại loại như:

q = forms.CharField(label='search', placeholder='Search')

Điều gì sẽ là cách tốt nhất để thực hiện điều này?

Câu trả lời:


281

Nhìn vào tài liệu vật dụng . Về cơ bản nó sẽ trông như:

q = forms.CharField(label='search', 
                    widget=forms.TextInput(attrs={'placeholder': 'Search'}))

Viết nhiều hơn, có, nhưng sự phân tách cho phép trừu tượng hóa tốt hơn các trường hợp phức tạp hơn.

Bạn cũng có thể khai báo một widgetsthuộc tính chứa <field name> => <widget instance>ánh xạ trực tiếp trên lớp con Metacủa bạn ModelForm.


Bạn có cần chỉ định forms.TextInputđể làm attrs={'placeholder': 'Search'}khai báo?
JhovaniC

1
@OvedD, tôi biết cái này đã cũ, nhưng hãy xem câu hỏi này: stackoverflow.com/questions/4341739/
Kẻ

1
@OvedD: xem câu trả lời của tôi để biết cách thực hiện điều này với ModelForm
Hamish Downer

1
Thật là ngu ngốc khi bạn phải chỉ định một tiện ích để thêm một trình giữ chỗ. Bạn sẽ có thể chỉnh sửa các thuộc tính tiện ích mà không cần ghi đè toàn bộ tiện ích ...
dspacejs

Đối với tiếng Trung Quốc, bạn cần có tiền tố như thế này: {'giữ chỗ': u '
搜索

60

Đối với ModelForm, bạn có thể sử dụng lớp Meta, do đó:

from django import forms

from .models import MyModel

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'name': forms.TextInput(attrs={'placeholder': 'Name'}),
            'description': forms.Textarea(
                attrs={'placeholder': 'Enter description here'}),
        }

Lưu ý rằng trong trường hợp này, bạn không thể chỉ định trường trong thân lớp.
Will S

Đây là phương pháp dễ nhất đối với tôi - và thật tuyệt khi tất cả các thuộc tính khác (nghĩa là bắt buộc) vẫn được tự động thêm vào mà tôi không phải chỉ định chúng.
JxAxMxIxN

41

Các phương pháp khác đều tốt. Tuy nhiên, nếu bạn không muốn chỉ định trường (ví dụ: đối với một số phương thức động), bạn có thể sử dụng:

def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['email'].widget.attrs['placeholder'] = self.fields['email'].label or 'email@address.nl'

Nó cũng cho phép trình giữ chỗ phụ thuộc vào thể hiện cho ModelForms với thể hiện được chỉ định.


7
Điều này thật tuyệt vời vì nó tránh được việc phải nhân đôi thời gian khởi tạo dài của các vật dụng cho các đối tượng phức tạp hơn như ModelMultipleChoiceField. Cảm ơn!
donturner

1
Tinh thần tương tự : for f in MyCommentForm.base_fields.values(): f.widget.attrs["placeholder"] = f.label, nhưng tôi thích phương thức constructor của bạn hơn.
jozxyqk

21

Bạn có thể sử dụng mã này để thêm attr giữ chỗ cho mọi trường TextInput trong biểu mẫu của bạn. Văn bản cho giữ chỗ sẽ được lấy từ nhãn trường mô hình.

class PlaceholderDemoForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PlaceholderDemoForm, self).__init__(*args, **kwargs)
        for field_name in self.fields:
            field = self.fields.get(field_name)  
            if field:
                if type(field.widget) in (forms.TextInput, forms.DateInput):
                    field.widget = forms.TextInput(attrs={'placeholder': field.label})

    class Meta:
        model = DemoModel

19

Câu hỏi tuyệt vời. Có ba giải pháp tôi biết về:

Giải pháp số 1

Thay thế widget mặc định.

class SearchForm(forms.Form):  
    q = forms.CharField(
            label='Search',
            widget=forms.TextInput(attrs={'placeholder': 'Search'})
        )

Giải pháp số 2

Tùy chỉnh các widget mặc định. Nếu bạn đang sử dụng cùng một tiện ích mà trường thường sử dụng thì bạn có thể chỉ cần tùy chỉnh tiện ích đó thay vì khởi tạo một tiện ích hoàn toàn mới.

class SearchForm(forms.Form):  
    q = forms.CharField(label='Search')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['q'].widget.attrs.update({'placeholder': 'Search'})

Giải pháp số 3

Cuối cùng, nếu bạn đang làm việc với một mẫu mô hình thì ( ngoài hai giải pháp trước đó ), bạn có tùy chọn chỉ định một tiện ích tùy chỉnh cho một trường bằng cách đặt widgetsthuộc tính của Metalớp bên trong .

class CommentForm(forms.ModelForm):  
    class Meta:
        model = Comment
        widgets = {
            'body': forms.Textarea(attrs={'cols': 80, 'rows': 20})
        }

1
Tôi đã định viết một giải pháp như là số 2 của bạn. Tôi muốn thêm rằng bạn có thể áp dụng các thao tác trên tất cả các trường bằng cách lặp lại self.fields, ví dụ:for field_name in self.fields: self.fields[field_name].widget.attrs.update({"placeholder": sth})
Alberto Chiusole

@AlbertoChiusole Có, bạn có thể, nếu đó là điều bạn muốn làm. Cảm ơn đã chỉ ra điều đó.
Dwayne Crooks

@DwayneCrooks Tôi khuyên bạn nên cập nhật số 3 theo giải pháp của cdosborn , vì nó ngắn hơn và dễ đọc hơn.
Mary

1

Thật không mong muốn khi phải biết cách khởi tạo một widget khi bạn chỉ muốn ghi đè giữ chỗ của nó.

    q = forms.CharField(label='search')
    ...
    q.widget.attrs['placeholder'] = "Search"

0

Hầu hết thời gian tôi chỉ muốn có tất cả các trình giữ chỗ bằng với tên dài dòng của trường được xác định trong các mô hình của tôi

Tôi đã thêm một mixin để dễ dàng thực hiện điều này với bất kỳ hình thức nào tôi tạo,

class ProductForm(PlaceholderMixin, ModelForm):
    class Meta:
        model = Product
        fields = ('name', 'description', 'location', 'store')

class PlaceholderMixin:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs):
        field_names = [field_name for field_name, _ in self.fields.items()]
        for field_name in field_names:
            field = self.fields.get(field_name)
            field.widget.attrs.update({'placeholder': field.label})

-2

Sau khi xem phương pháp của bạn, tôi đã sử dụng phương pháp này để giải quyết nó.

class Register(forms.Form):
    username = forms.CharField(label='用户名', max_length=32)
    email = forms.EmailField(label='邮箱', max_length=64)
    password = forms.CharField(label="密码", min_length=6, max_length=16)
    captcha = forms.CharField(label="验证码", max_length=4)

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    for field_name in self.fields:
        field = self.fields.get(field_name)
        self.fields[field_name].widget.attrs.update({
            "placeholder": field.label,
            'class': "input-control"
        })

2
Xin lưu ý rằng nội dung phải bằng tiếng Anh trên Stack Overflow. Bên cạnh đó, đây dường như là một bài viết "tôi cũng vậy", thay vì một câu trả lời cho câu hỏi được đặt ra ở trên.
TylerH

Tôi sẽ nói rằng bài viết "tôi cũng vậy" là ổn nếu họ thêm chi tiết. Điều gì về phương pháp này khác với bất kỳ phương pháp nào khác? Kỹ thuật hoặc học tập thiết yếu ở đây là gì?
halfer
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.