【问题标题】:Need guidance with FilteredSelectMultiple widget需要 FilteredSelectMultiple 小部件的指导
【发布时间】:2020-01-09 06:02:13
【问题描述】:

很抱歉,如果这个问题可能变得有点宽泛,但由于我只是在学习 django(而且我只是业余开发者),我需要一些指导,我希望这些指导能在未来帮助像我这样的人,因为我找不到有关使用此小部件的任何清晰易懂的指南。有了您的回答和帮助,我将尝试使这个问题线程至少具有指导意义。

我发现对这个主题有些帮助的材料:

Django multi-select widget?

Django: Replacement for the default ManyToMany Widget of Forms

Django's FilteredSelectMultiple widget only works when logged in

Django FilteredSelectMultiple not rendering on page

Use the Django admin app's FilteredSelectMultiple widget in form

Get the chosen values from FilteredSelectMultiple widget in Django

Django FilteredSelectMultiple Right Half Does Not Render

其他链接很少,但它们没有使任何内容更清晰或添加新信息,因此我不会提及它们。

这是我设法理解的(如果我错了,请纠正我或添加我遗漏的任何内容):

要首先创建FilteredSelectMultiple 小部件,我需要修改forms.py(就像在任何其他小部件创建过程中一样)。修改后的forms.py 应该有from django.contrib.admin.widgets import FilteredSelectMultiple 导入和Media 类。 forms.py 代码应如下所示(请纠正我,因为可能某处有问题):

from django import forms
from catalog.models import DrgCode  
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.conf import settings #without it I get an error that settings not defined

class CalculatorForm(forms.Form):
    drg_choice = forms.ModelMultipleChoiceField(queryset=DrgCode.objects.all(), widget=FilteredSelectMultiple("Somethings", is_stacked=False), required=True)

    class Media:
        css = {
            'all': (os.path.join(settings.BASE_DIR, '/static/admin/css/widgets.css'),),
        }
        js = ('/admin/jsi18n',)

关于这部分的问题:

  1. 我对 django.conf 导入是否正确?因为没看到 在我找到的任何材料中导入。 答案:在我的测试过程中,我确定如果使用settings.BASE_DIR 部分,则必须导入django.conf。在各种来源中,有两种编写 css 路径的方法,这一种对我有用。
  2. 我需要创建widgets.css 和相应的目录吗?要么 django会自己找到吗?由于没有这样的文件或目录 在我使用django-admin startproject cmd 创建骨架网站后生成? 回答:不需要。不需要创建 widgets.css 或任何文件,因为 django 会自己找到它们。
  3. 与之前jsi18n 部分的问题相同。还有这是什么?一世 假设它的 javascript 文件,但由于某种原因它没有扩展名。 我也无法在任何地方找到它?我应该创建它吗?怎么做? 或者我可以从某个地方复制它? 部分答案:不需要创建它。只需在urls.py 中指向它。仍然不知道它是什么类型的文件(或它在哪里)

修改forms.py后我应该修改urls.py添加url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', name='jsi18n')

所以urls.py 现在看起来像这样:

from django.urls import path
from . import views
from django.conf.urls import url 


urlpatterns = [
    path('', views.index, name='index'),
    'django.views.i18n.javascript_catalog',
    name='jsi18n'),
]

问题:

  1. 我这样做是正确的还是应该将其添加到urlpatterns 下方? 回答:这个方法就好了。

现在我需要设置HTML 模板文件以供表单呈现(就像在任何其他情况下一样)。它的代码(文件名为DrgCalculator.html):

{% extends "base_generic.html" %}
   <script type="text/javascript" src="{% url 'jsi18n' %}" > </script>

  {{ form.media }}

  <form enctype="multipart/form-data" method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit" class="save btn btn-default">Submit</button>
  </form>
  1. 这部分似乎或多或少清晰。但也许我应该修改 某事或知道什么? 答:应该改。下面会写完整的代码。

最后我需要调整views.py 来设置这个表单以及与之相关的所有事情发生的位置。

据我了解,这部分的代码或多或少与小部件没有直接关系,但为了完成所有内容并制作工作示例,我将使用我在this (very good) django tutorial 中学习/获得的代码:

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse

from catalog.models import DrgCode
from catalog.forms import CalculatorForm

def DrgCalculator(request):
    if request.method == 'POST':
        form = CalculatorForm(request.POST)
        if form.is_valid():
            return render(request, 'DrgCalculator.html')
    context = {
        'form': form,
    }
    return render(request, 'DrgCalculator.html', context)

问题:

  1. 对这部分代码有什么意见吗? 答案:缺少else: form = DrgCalculator()。将在下面编写修改后的代码。
  2. 我将如何访问用户选择使用的值 FilteredSelectMultiple?我想我应该清理数据 forms.py 与其他小部件一样。所以我应该添加嵌套函数 下面到我的class CalculatorFormforms.py,对吗? 回答:是的,应该像其他情况一样清理数据。功能正确。

    def clean_CalculatorForm(self): drg_choice = self.cleaned_data['drg_choice'] return drg_choice

  3. 清理后我将获得的数据是列表还是字典?我是不是 正确的? 回答:否,从这个小部件中作为 QuerySet 接收的用户输入

这就是我所有的问题,对不起,长线程,我试图让它尽可能清楚。如果我需要澄清一些事情,请告诉我。我将尝试编辑和更新此内容,以使其对将来阅读它的人友好。

EDIT1:回答了我的一些问题。

EDIT2:回答了我的其余问题。

【问题讨论】:

  • 我们不都是从某个地方开始的吗? :D

标签: python django python-3.x django-forms


【解决方案1】:

经过几天的研究和测试,我设法让FilteredSelectMultiple 小部件以用户形式在管理页面之外工作。正如所承诺的那样,我将尝试将我积累的知识综合成某种指南,希望将来能对像我这样的人有所帮助。请注意,我远非专业人士(确切地说,只是一个没有计算机工程背景的业余爱好者),所以我的观察可能并不完全正确,或者我的做法不是最好的,但它可能会帮助你正确跟踪。

因此,从FilteredSelectMultiple 小部件forms.py 开始,必须通过导入小部件、为其创建字段(类似于常规小部件)并添加嵌套的Media 类来修改。代码示例:

from django.contrib.admin.widgets import FilteredSelectMultiple    

class DrgCalculator(forms.Form):
        drg_choise = forms.ModelMultipleChoiceField(queryset=DrgCode.objects.all(),
                                                          label="Something",
                                                          widget=FilteredSelectMultiple("Title", is_stacked=False),
                                                          required=True)

        class Media:
            css = {
                'all': ('/static/admin/css/widgets.css',),
            }
            js = ('/admin/jsi18n',)

        def clean_drg_choise(self):
            drg_choise = self.cleaned_data['drg_choise']
            return drg_choise

正如我在测试和研究期间确定的那样,class Media 应该按原样复制,并且不需要更改小部件即可工作。本课程中提到的文件将由 django 自己找到,因此无需搜索和复制它们(就像我阅读的一些材料中所说的那样)。

创建表单urls.py 后应进行修改。在测试期间我发现,在较新的 django 版本(或至少我使用的一个)中,javascript_catalog 被重命名,并且提供的 url 不能是字符串。所以代码应该是这样的:

from django.urls import path
from . import views
from django.conf.urls import url
from django import views as django_views

urlpatterns = [
    url(r'^jsi18n/$', django_views.i18n.JavaScriptCatalog.as_view(), name='jsi18n'),
]

现在对于htlm 模板,我确信还有更多方法可以做到这一点,所以我只提供示例:

{% extends "base_generic.html" %}

{% block content %}
<div id='frame'>
    <form action="" method="post">
        <div id='sk_body'>
            <fieldset>
            <legend>Fill required fields</legend>      
                <form>
                    {% csrf_token %}
                    <table>
                        {{ form.media }}
                        {{ form.as_table }}
                        <script type="text/javascript" src="{% url 'jsi18n' %}"></script>
                    </table>
                        <input type="submit" value="Count">
                </form>
            </fieldset>
        </div>
    </form>
</div>
{% endblock %}

要从这个小部件接收数据,应该使用views.py 中相当标准的代码,我使用的示例代码:

def DRG_calcualtor(request):
    if request.method == 'POST':
        form = DrgCalculator(request.POST)
        if form.is_valid():
            choosen_drg = form.cleaned_data['drg_choise'] #result as QuerySet
            choosen_drg_list = list([str(i) for i in choosen_drg]) #you can convert it to list or anything you need             

            return render(request, 'DRGcalculator_valid.html')

        context = {
            'form': form,
            }
        return render(request, 'DRGcalculator.html', context)

    else:
        form = DrgCalculator()
    context = {
        'form': form,
        }
    return render(request, 'DRGcalculator.html', context)

【讨论】:

  • FilteredSelectMultiple 的问题是它只在您以管理员身份登录时才有效
猜你喜欢
  • 1970-01-01
  • 2015-04-21
  • 2022-06-23
  • 2018-02-02
  • 1970-01-01
  • 2021-09-15
  • 2013-01-20
  • 2016-03-13
  • 2016-12-13
相关资源
最近更新 更多