模型对象的 Django 选择

Django choices with model objects

是的,这是一项作业,是的,我花了一些时间在上面,现在我需要帮助。

我的任务有两个模型,ServerClient,它们是 1-N 关系。如下所述

# models.py
class Server(models.Model):
    name = models.CharField(max_length=255, unique=True, null=False, blank=False)
    maximum_clients = models.IntegerField(default=1,null=False, blank=False)

class Client(models.Model):
    name = models.CharField(max_length=255, unique=True, null=False, blank=False)
    active = models.BooleanField(default=True)
    server = models.ForeignKey(Server)

我用 ModelForm 创建了一个表单,它允许我在给定的服务器上创建一个新的客户端,但任务的先决条件是只提供有空闲容量的服务器(它们的 maximum_clients 小于实际客户)所以这就是我所做的

#forms.py
from django.db.models import Count

qs = Server.objects.annotate(Count('client'))
server_choices = []
for server in qs:
    if server.client__count < server.maximum_clients:
        server_choices.append((server,server))

class ClientForm(forms.ModelForm):
    name = forms.CharField(label='Client name')
    server = forms.ChoiceField(choices=server_choices)
    class Meta:
        model = Client
        fields = ('name','server',)

此方法根据我提到的先决条件使用正确的服务器填充 select。但是,保存此表单会产生错误,例如 Cannot assign "u'fifty'": "Client.server" must be a "Server" instance. Fifty is the name of the server with maximum_clients = 50

admin 屏幕上有一个类似的表格,我也对其进行了修改以仅显示可用的服务器并在此处保存会产生相同的错误。

这不是正确的方法。除了您看到的错误之外,您还会发现 server_choices 仅在您重新启动网络服务器时更新,而不是在服务器对象本身发生更改时更新。

您有一个外键,需要从相关对象的子集中select。正确的字段是 ModelChoiceField;这需要一个查询集,您可以在定义中对其进行过滤。由于您的过滤器依赖于同一模型中的字段,因此您需要使用 F 对象。

class ClientForm(forms.ModelForm):
    name = forms.CharField(label='Client name')
    server = forms.ModelChoiceField(
        queryset=Server.objects.annotate(client_count=Count('client')).filter(client_count__lt=F('maximum_clients')
    )