Django 表单“'ForwardManyToOneDescriptor' 对象没有属性 'all'”

Django Form "'ForwardManyToOneDescriptor' object has no attribute 'all'"

我遇到了很多问题。实际上,尝试将表单添加到主页,并根据数据库对象为用户提供 select 的选项。然后提交后页面会刷新,表单就可以再次使用了。

Forms.py:

rom django import forms
from django.forms import ChoiceField, ModelForm, RadioSelect
from .models import command_node


class command_form(ModelForm):
    class Meta:
        model = command_node
        fields = (
            'host_id',
            'current_commands'
        )

        host_id = forms.ModelChoiceField(
            required=True,
            queryset=command_node.host_id,
            widget=forms.Select(
                attrs={
                    'class': 'form-control'
                },
            )
        )

        current_comamnds = forms.ChoiceField(
            required=True,
            attrs={
                'class': 'form-control'
            },
            
            choices=[
                ('Sleep', "Sleep"),
                ('Open SSH_Tunnel', 'Open SSH_Tunnel'),
                ('Close SSH_Tunnel', 'Close SSH_Tunnel'),
                ('Open TCP_Tunnel', 'Open TCP_Tunnel'),
                ('Close TCP_Tunnel', 'Close TCP_Tunnel'),
                ('Open Dynamic', 'Open Dynamic'),
                ('Close Dynamic', 'Close Dynamic'),
                ('Task', 'Task'),
            ])

Models.py:

from tkinter import CASCADE
from turtle import update
from django.db import models

class beacon(models.Model):
    host_id = models.BigAutoField('Id', primary_key=True)
    hostname = models.CharField('Hostname', max_length=200)
    internalIp = models.CharField('Internal-IP', max_length=200)
    externalIp = models.CharField('External-IP', max_length=200)
    current_user = models.CharField('Current_User', max_length=200)
    os = models.CharField('OS', max_length=200)
    admin = models.CharField('Admin', max_length=200)
    
    def __str__(self):
        return self.hostname

class command_node(models.Model):
    host_id = models.ForeignKey(beacon, on_delete=models.CASCADE)
    current_commands = models.CharField('current_command', max_length=50, null=True)
    previous_commands = models.CharField('previous_commands', max_length=2000, null=True)
    
    def __str__(self):
        return str(self.host_id)

views.py:

from django.shortcuts import render
from django.http import HttpResponse
from .models import beacon
from .models import command_node
from .forms import command_form
from django.http import HttpResponseRedirect

def home(request):
    form = command_form,
    if request.method == "POST":
            form = form(request.POST)
            if form.is_valid():
                form.save()
                return render(request, 'home.html', context)
    context = {'form':form},
    return render(request, 'home.html', context)

相关HTML部分:

</br>
</br>
    <form action="" method=POST>
        {% csrf_token %}
        {{ form.as_p }}
        {{form}}
        <button type="Submit" class="btn btn-secondary btn-sm">Submit</button>
    </form>
</body>
</html>

urls.py:

from django.contrib import admin
from django.urls import path
from django.urls import include, re_path
from .forms import command_node
from . import views

urlpatterns = [
    re_path('home/', views.home)
]

当我尝试 运行 服务器甚至现在迁移时,我得到以下信息。

PS C:\Python-projects\commandsite> python manage.py makemigrations
Traceback (most recent call last):
  File "C:\Python-projects\commandsite\manage.py", line 22, in <module>
    main()
  File "C:\Python-projects\commandsite\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 455, in execute
    self.check()
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\management\base.py", line 487, in check
    all_issues = checks.run_checks(
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\checks\registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\checks\urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\checks\urls.py", line 24, in check_resolver
    return check_method()
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\urls\resolvers.py", line 480, in check
    for pattern in self.url_patterns:
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\urls\resolvers.py", line 696, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\urls\resolvers.py", line 689, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\Python-projects\commandsite\commandsite\urls.py", line 22, in <module>
    re_path('website/', include('website.urls'))
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\urls\conf.py", line 38, in include
    urlconf_module = import_module(urlconf_module)
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "C:\Python-projects\commandsite\website\urls.py", line 4, in <module>
    from .forms import command_node
  File "C:\Python-projects\commandsite\website\forms.py", line 6, in <module>
    class command_form(ModelForm):
  File "C:\Python-projects\commandsite\website\forms.py", line 7, in command_form
    class Meta:
  File "C:\Python-projects\commandsite\website\forms.py", line 14, in Meta
    host_id = forms.ModelChoiceField(
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\models.py", line 1463, in __init__
    self.queryset = queryset
  File "C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\models.py", line 1488, in _set_queryset
    self._queryset = None if queryset is None else queryset.all()
AttributeError: 'ForwardManyToOneDescriptor' object has no attribute 'all'
PS C:\Python-projects\commandsite>

在我尝试添加表单之前,这一切都有效。由于修改它以尝试获取表单,这就是我面临的问题。因此,任何帮助都会得到极大的应用。因为我不知道我做错了什么。

查看您的代码,出现错误是因为您在表单中指定了 queryset=command_node.host_id

    host_id = forms.ModelChoiceField(
        required=True,
        queryset=command_node.host_id,
        widget=forms.Select(
            attrs={
                'class': 'form-control'
            },
        )
    )

实际上,command_node.host_id 是一个 ForwardManyToOneDescriptor(这是分配给标记为 ForeignKey 的字段的 class)。在这种情况下,您想要作为 queryset parameter 提供的是一组应该属于模型 beacon 的对象,它是与 host_id:

关联的一个对象
    host_id = forms.ModelChoiceField(
        required=True,
        queryset=beacon.objects.all(),
        widget=forms.Select(
            attrs={
                'class': 'form-control'
            },
        )
    )

这将在您的数据库中将所有 beacon 对象显示为表单下拉列表中的选项(使用的小部件是 Select)。您还可以显示与 beacon 模型相关的任何查询集。例如,如果您只想显示内部 IP 等于 X.Y.Z.Wbeacon 个对象,您可以指定 queryset=beacon.objects.filter(internalIP="X.Y.Z.W").

这里需要注意的几点:

  • Django 在显示依赖于 ForeignKey 的字段的可用选项时已经使用了 ModelChoiceField。您可以在此处检查 Django 在 Model 字段和 Form 字段之间建立的关联:https://docs.djangoproject.com/en/4.0/topics/forms/modelforms/#field-types。如果您希望所有 beacon 对象都能够在您的表单中进行选择,您的代码可以简化为:
class command_form(ModelForm):
    class Meta:
        model = command_node
        fields = (
            'host_id',
            'current_commands'
        )

        current_comamnds = forms.ChoiceField(
            required=True,
            attrs={
                'class': 'form-control'
            },
            
            choices=[
                ('Sleep', "Sleep"),
                ('Open SSH_Tunnel', 'Open SSH_Tunnel'),
                ('Close SSH_Tunnel', 'Close SSH_Tunnel'),
                ('Open TCP_Tunnel', 'Open TCP_Tunnel'),
                ('Close TCP_Tunnel', 'Close TCP_Tunnel'),
                ('Open Dynamic', 'Open Dynamic'),
                ('Close Dynamic', 'Close Dynamic'),
                ('Task', 'Task'),
            ])