假设我在我的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)
也就是说,有多个公司,每个公司都有一系列的费率和客户。每个客户都应该有一个从其母公司的利率中选择的基础利率,而不是其他公司的利率。
当创建一个添加客户端表单时,我想删除公司选项(因为已经通过公司页面上的“添加客户端”按钮进行了选择),并将费率选项限制为该公司。
在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。看起来很有前途,但我不知道如何在公司里过关。id和我不清楚,如果这将工作以外的管理界面无论如何。
谢谢。(这似乎是一个非常基本的要求,但如果我应该重新设计一些东西,我愿意听取建议。)
除了S.Lott的回答和评论中提到的becomingGuru,还可以通过覆盖ModelForm来添加查询集过滤器。__init__函数。(这可以很容易地应用于常规表单)它可以帮助重用并保持视图函数的整洁。
class ClientForm(forms.ModelForm):
def __init__(self,company,*args,**kwargs):
super (ClientForm,self ).__init__(*args,**kwargs) # populates the post
self.fields['rate'].queryset = Rate.objects.filter(company=company)
self.fields['client'].queryset = Client.objects.filter(company=company)
class Meta:
model = Client
def addclient(request, company_id):
the_company = get_object_or_404(Company, id=company_id)
if request.POST:
form = ClientForm(the_company,request.POST) #<-- Note the extra arg
if form.is_valid():
form.save()
return HttpResponseRedirect(the_company.get_clients_url())
else:
form = ClientForm(the_company)
return render_to_response('addclient.html',
{'form': form, 'the_company':the_company})
这对于重用很有用,比如如果在许多模型上需要通用的过滤器(通常我声明一个抽象的Form类)。如。
class UberClientForm(ClientForm):
class Meta:
model = UberClient
def view(request):
...
form = UberClientForm(company)
...
#or even extend the existing custom init
class PITAClient(ClientForm):
def __init__(company, *args, **args):
super (PITAClient,self ).__init__(company,*args,**kwargs)
self.fields['support_staff'].queryset = User.objects.exclude(user='michael')
除此之外,我只是在重申Django博客材料,那里有很多好的材料。
所以,我真的试图理解这一点,但似乎Django仍然没有使它非常简单。我不是那么笨,但我就是看不到任何(多少)简单的解决办法。
我发现对于这类事情,必须覆盖Admin视图通常是非常丑陋的,而且我发现的每个示例都不能完全应用于Admin视图。
这在我做的模型中是很常见的情况,我发现没有明显的解决方案是令人震惊的……
我有这些类:
# models.py
class Company(models.Model):
# ...
class Contract(models.Model):
company = models.ForeignKey(Company)
locations = models.ManyToManyField('Location')
class Location(models.Model):
company = models.ForeignKey(Company)
这在为Company设置Admin时产生了一个问题,因为它有内联的合同和位置,合同的m2m位置选项没有根据您当前编辑的公司进行适当的过滤。
简而言之,我需要一些管理选项来做这样的事情:
# admin.py
class LocationInline(admin.TabularInline):
model = Location
class ContractInline(admin.TabularInline):
model = Contract
class CompanyAdmin(admin.ModelAdmin):
inlines = (ContractInline, LocationInline)
inline_filter = dict(Location__company='self')
最终,我不关心过滤过程是放在基础CompanyAdmin上,还是放在ContractInline上。(将它放在内联更有意义,但它很难将基契约引用为“self”。)
有人知道像这条急需的捷径一样简单的东西吗?当我为这类事情创建PHP管理员时,这被认为是基本功能!事实上,它总是自动的,如果你真的不想要它,就必须关闭它!