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). Если вы примете это соглашение об именовании, отличить класс от его экземпляров будет проще.
  • .
Вернуться на верх