【问题标题】:how to create a autocomplete input field in a form using Django如何使用 Django 在表单中创建自动完成输入字段
【发布时间】:2018-10-27 02:12:10
【问题描述】:

我对 django 及其方式非常陌生。我正在尝试为表单创建一个自动完成字段。我的代码如下

forms.py

from django import forms

class LeaveForm(forms.Form):
    leave_list = (
        ('Casual Leave', 'Casual Leave'),
        ('Sick Leave', 'Sick Leave')
    )
    from_email = forms.EmailField(required=True, widget=forms.TextInput(attrs={'style': 'width: 400px'}))
    start_date = end_date = forms.CharField(widget=forms.TextInput(attrs={'type': 'date', 'style': 'width: 175px'}))
    leave_type = forms.ChoiceField(choices=leave_list, widget=forms.Select(attrs={'style': 'width: 400px'}))
    comments = forms.CharField(required=True, widget=forms.Textarea(attrs={'style': 'width: 400px; height: 247px'}))

    def clean_from_email(self):
        data = self.cleaned_data['from_email']
        if "@testdomain.com" not in data:
            raise forms.ValidationError("Must be @testdomain.com")
        return data

我想要实现的是,当用户在"From Email" 字段中键入单词时,我存储在外部数据库中的电子邮件列表应该出现在自动完成列表选项中。

models.py

from django.db import models


class ListOfUsers(models.Model):
    emp_number = models.CharField(db_column='Emp_Number', primary_key=True, max_length=50, unique=True)  # Field name made lowercase.
    name = models.CharField(db_column='Name', max_length=40)  # Field name made lowercase.
    supervisor = models.CharField(db_column='Supervisor', max_length=40)  # Field name made lowercase.
    email = models.CharField(db_column='Email', max_length=50, blank=False, null=False, unique=True)  # Field name made lowercase.


    class Meta:
        managed = False
        db_table = 'List of users'

知道如何做到这一点吗?

更新:

我开始使用 django-autocomplete-light,现在能够从自动完成 url 中得到回复。看起来是这样的

{"results": [{"id": "user1@mydomain.com", "text": "user1@mydomain.com"}, {"id": "user2@mydomain.com", "text": "user2@mydomain.com"}, {"id": "user3@mydomain.com", "text": "user3@mydomain.com"}]}

views.py

class EmailAutocomplete(autocomplete.Select2ListView):
    def get_list(self):
        qs = ListOfUsers.objects.using('legacy')

        if self.q:
            qs = qs.filter(email__icontains=self.q).values_list('email', flat=True)

        return qs

我仍然不知道如何让这些数据出现在"from_email"字段中

【问题讨论】:

  • 它需要客户端(即 Javascript)编码和 Ajax。如果你没有这些经验,有几个 Django 包用于实现自动完成字段。谷歌搜索可能会有所帮助。
  • 知道哪个软件包易于学习。 Autocomolete-light 对我来说毫无意义

标签: python django autocomplete django-autocomplete-light


【解决方案1】:

添加的很少。 Abilash 的回答很好,也很清楚。 但如果它对您不起作用,您可能应该将 basicAutoComplete 激活包装到

$(document).ready(function(){
};

原因和一些解释可以在这里找到: Bootstrap Auto-complete Error: Cannot read property " " of undefined

【讨论】:

    【解决方案2】:

    我终于使用此处找到的说明进行了自动完成搜索

    https://github.com/xcash/bootstrap-autocomplete
    https://bootstrap-autocomplete.readthedocs.io/en/latest/

    使用非常简单,不需要在settings.py中安装任何应用程序,它适用于bootstrap 3和bootstrap 4

    还有很多其他可用的包,但这很简单,很容易满足我的需要。

    我将解释我使用的代码

    page.html

    {% block script %}
        <script src="https://cdn.rawgit.com/xcash/bootstrap-autocomplete/3de7ad37/dist/latest/bootstrap-autocomplete.js"></script>
        <script>
            $('.basicAutoComplete').autoComplete(
                {minLength: 1}
            );
            $('.dropdown-menu').css({'top': 'auto', 'left': 'auto'})
    
        </script>
    {% endblock %}
    .
    .
    .
    .
    .
    {% if field.name == "from_email" %}
       {% render_field field class="basicAutoComplete form-control" %}
    {% else %}
       {% render_field field class="form-control" %}
    {% endif %}
    

    autoComplete 是调用以执行操作的函数,minLength 指定执行提取操作之前文本的最小长度 我添加了一个额外的 CSS 来修复自动完成下拉菜单,否则这很奇怪。

    Jinja 渲染不断覆盖视图中的类定义,因此我添加了一个 if 检查。

    urls.py

    from . import views
    
    urlpatterns = [
        .
        .
        .
        path('email_autocomplete/', views.email_autocomplete, name='email_autocomplete')
    ]
    

    将此行添加到urls.py

    forms.py

    class LeaveForm(forms.Form):
        from_email = forms.EmailField(required=True, widget=forms.TextInput(
            attrs={
                'style': 'width: 400px',
                'class': 'basicAutoComplete',
                'data-url': "/domain/email_autocomplete/"
            }))
    

    以上是forms.py中输入字段的代码。 data-url 指向生成 JSON 结果的位置。

    views.py

    from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
    from .models import model
            
    def email_autocomplete(request):
        if request.GET.get('q'):
            q = request.GET['q']
            data = model.objects.using('legacy').filter(email__startswith=q).values_list('email',flat=True)
            json = list(data)
            return JsonResponse(json, safe=False)
        else:
            HttpResponse("No cookies")
                
    

    这对我来说是最令人困惑的部分。 GET 请求很容易理解,但是将数据从 model.objects 转换为 JSON 格式的对象需要一段时间。诀窍是使用

    values_list('columnName',flat=True)
    

    从数据库中过滤数据时,然后使用list(data)转换为列表,最后使用JsonResponse将其转换为JSON。

    希望这对任何想要简单自动完成的人有所帮助

    【讨论】:

    • 感谢您分享此解决方案。我正在尝试遵循您的示例,并尝试将其与基于类的视图 CreateView 相结合。有没有办法做到这一点?如果是这样,我还需要 JsonResponce 的单独网址吗?我很乐意分享我的代码,或者如果您能多解释一下这些观点,我将不胜感激。我在一个单独的预期文本列表中进行管道传输(未连接到我的模型实例),因此我对创建 json 对象不太感兴趣,而对视图的一般外观更感兴趣。请记住,我来自基于通用类的视图。非常感谢
    • 这太棒了。我完全迷失了 django auto-complete-light。
    • @TravisN.Miller 很抱歉有段时间没有来过这里。你还需要帮助吗?
    • 很棒的帖子,比 django-autocomplete-light 更简单、更健壮,我无法在模态中工作...
    • 事实上 Django 在 admin.ModelAdmin 类中提出了这个功能,并带有属性“autocomplete_fields”。为什么这在自定义表单中也没有?
    猜你喜欢
    • 2012-01-03
    • 1970-01-01
    • 2017-11-16
    • 2012-05-28
    • 2017-05-30
    • 1970-01-01
    • 2022-11-28
    • 2019-11-30
    • 2016-06-19
    相关资源
    最近更新 更多