Django Form " Объект "ForwardManyToOneDescriptor" не имеет атрибута 'all'"
Здравствуйте, у меня возникли некоторые проблемы. По сути, я пытаюсь добавить форму на домашнюю страницу с опциями, которые пользователь может выбрать на основе объекта БД. Затем, после отправки, страница обновляется, и форма может быть использована снова.
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)
]
Когда я пытаюсь запустить сервер или даже сейчас выполнить миграцию, я получаю следующее.
Все это работало до того, как я попытался добавить форму. После того, как я попытался добавить форму, я столкнулся с этой проблемой. Поэтому любая помощь будет очень кстати. Поскольку я не знаю, что я сделал неправильно.
Глядя на ваш код, ошибка возникает из-за того, что вы указываете 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
). В данном случае, то, что вы хотите предоставить в качестве queryset
параметра - это набор объектов, которые должны принадлежать модели beacon
, которая является onea, связанной с host_id
:
host_id = forms.ModelChoiceField(
required=True,
queryset=beacon.objects.all(),
widget=forms.Select(
attrs={
'class': 'form-control'
},
)
)
Это отобразит все beacon
объекты в вашей БД в виде опций в выпадающем окне вашей формы (используемый виджет - Select
). Вы также можете отобразить любой набор запросов, связанный с моделью beacon
. Например, если вы хотите отобразить только те объекты beacon
, которые имеют внутренний IP, равный X.Y.Z.W
, вы можете разделить queryset=beacon.objects.filter(internalIP="X.Y.Z.W")
.
Здесь следует отметить некоторые моменты:
- Django уже использует
ModelChoiceField
при отображении доступных опций для полей, которые полагаются наForeignKey
. Вы можете проверить ассоциации, которые 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
вместоsnake_case
(см. https://visualgit.readthedocs.io/en/latest/pages/naming_convention.html#classes). Если вы примете это соглашение об именовании, отличить класс от его экземпляров будет проще. .