说我的 models.py
中有以下内容:
class Company(models.Model):
name = ...
class Rate(models.Model):
company = models.ForeignKey(Company)
name = ...
class Client(models.Model):
name = ...
company = models.ForeignKey(Company)
base_rate = models.ForeignKey(Rate)
即有多个 Companies
,每个都有 Rates
和 Clients
的范围 . 每个 Client
都应该有一个基础 Rate
,它是从它的父级 Company's Rates
中选择的,而不是另一个 Company's Rates
.
在创建用于添加 Client
的表单时,我想删除 Company
选项(因为已经通过 Company
页面上的"Add Client"按钮选择了该选项)并将 Rate
选项限制为 Company
.
我如何在Django 1.0中解决这个问题?
我目前的 forms.py
文件只是样板文件:
from models import *
from django.forms import ModelForm
class ClientForm(ModelForm):
class Meta:
model = Client
views.py
也是基本的:
from django.shortcuts import render_to_response, get_object_or_404
from models import *
from forms import *
def addclient(request, company_id):
the_company = get_object_or_404(Company, id=company_id)
if request.POST:
form = ClientForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(the_company.get_clients_url())
else:
form = ClientForm()
return render_to_response('addclient.html', {'form': form, 'the_company':the_company})
在Django 0.96中,我能够在渲染模板之前通过执行以下操作来破解它:
manipulator.fields[0].choices = [(r.id,r.name) for r in Rate.objects.filter(company_id=the_company.id)]
ForeignKey.limit_choices_to似乎很有希望,但我不知道如何传递 the_company.id
并且我不清楚它是否会在Admin界面之外工作 .
谢谢 . (这似乎是一个非常基本的要求,但如果我重新设计一些东西,我愿意接受建议 . )
7 回答
ForeignKey由django.forms.ModelChoiceField表示,它是ChoiceField,其选择是模型QuerySet . 请参阅ModelChoiceField的参考 .
因此,为字段的
queryset
属性提供QuerySet . 取决于您的表单是如何构建的 . 如果您构建显式表单,则会直接命名 .如果采用默认的ModelForm对象,
form.fields["rate"].queryset = ...
这在视图中明确完成 . 没有黑客攻击 .
除了S.Lott的答案和在评论中提到的BecomeGuru之外,还可以通过覆盖
ModelForm.__init__
函数来添加查询集过滤器 . (这可以很容易地应用于常规表单)它可以帮助重用并保持视图功能整洁 .如果您在许多模型上需要通用过滤器(通常我声明一个抽象的Form类),这对重用来说很有用 . 例如 .
除此之外,我只是重述Django博客材料,其中有很多好的博客材料 .
这很简单,适用于Django 1.4:
您不需要在表单类中指定它,但可以直接在ModelAdmin中指定它,因为Django已经在ModelAdmin上包含了这个内置方法(来自文档):
更简单的方法(例如,创建用户可以访问的前端管理界面)是继承ModelAdmin,然后更改下面的方法 . 最终结果是一个用户界面,它只显示与它们相关的内容,同时允许您(超级用户)查看所有内容 .
我已经覆盖了四种方法,前两种方法使得用户无法删除任何内容,它还会删除管理站点中的删除按钮 .
第三个覆盖过滤任何包含引用的查询(在示例'user'或'porcupine'中(仅作为说明) .
最后一个覆盖过滤模型中的任何foreignkey字段,以过滤与基本查询集相同的可用选项 .
通过这种方式,您可以呈现一个易于管理的前端管理站点,允许用户弄乱自己的对象,而且您不必记住键入我们上面讨论过的特定ModelAdmin过滤器 .
删除“删除”按钮:
防止删除权限
过滤可在管理网站上查看的对象:
筛选管理站点上所有foreignkey字段的选项:
要使用通用视图执行此操作,例如CreateView ...
最重要的部分......
,read my post here
如果您尚未创建表单并想要更改查询集,则可以执行以下操作:
当您使用通用视图时,这非常有用!
所以,我真的试图理解这一点,但似乎Django仍然没有让这个非常简单 . 我不是那么愚蠢,但我看不出任何(有点)简单的解决方案 .
我发现为这种事情重写管理员视图通常非常难看,我发现的每个例子都不会完全适用于管理员视图 .
对于我制作的模型来说,这是一个常见的情况,我发现它没有明显的解决方案......
我有这些课程:
这在设置Admin for Company时会产生问题,因为它具有 Contract 和位置的内联,并且根据您当前正在编辑的公司未正确过滤Contract的m2m选项 .
简而言之,我需要一些管理选项来执行以下操作:
最后,我不在乎过滤过程是放在基础CompanyAdmin上,还是放在ContractInline上 . (将它放在内联上更有意义,但是很难将基本 Contract 称为“自我” . )
有没有人知道像这个急需的捷径一样直截了当的东西?回来当我为这类东西做PHP管理员时,这被认为是基本功能!事实上,它总是自动的,如果你真的不想要它就必须被禁用!
更公开的方法是在Admin类中调用get_form . 它也适用于非数据库字段 . 例如,我在表单上有一个名为'_terminal_list'的字段,可以在特殊情况下用于从get_list(请求)中选择多个终端项,然后根据request.user进行过滤: