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.W
的 beacon
个对象,您可以指定 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'),
])
- Python(因此在 Django 中也是如此)的一个常见做法是在
UpperCaseCamelCase
中写 class 名称而不是 snake_case
(参见 https://visualgit.readthedocs.io/en/latest/pages/naming_convention.html#classes ).如果您采用此命名约定,将 class 与其实例区分开来会更容易。
我遇到了很多问题。实际上,尝试将表单添加到主页,并根据数据库对象为用户提供 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.W
的 beacon
个对象,您可以指定 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'),
])
- Python(因此在 Django 中也是如此)的一个常见做法是在
UpperCaseCamelCase
中写 class 名称而不是snake_case
(参见 https://visualgit.readthedocs.io/en/latest/pages/naming_convention.html#classes ).如果您采用此命名约定,将 class 与其实例区分开来会更容易。