django 1.2 change_form 中编辑修改ForeignKey的值

本文介绍了如何在Django 1.2的admin界面中,通过自定义TabularInline类,实现当编辑Buy模型时,同时修改与其关联的from_people和to_people两个外键值。展示了默认效果与目标效果的对比,并提供了具体的代码示例,最终实现了在编辑Buy时,能够直观地修改People外键的相关信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Model如下

class People(models.Model):
name = models.CharField(max_length = 200)
def __unicode__(self):
return force_unicode(self.name)

class Buy(models.Model):
from_people = models.ForeignKey(People, related_name = 'from_people')#related_name must be 'from_people'
to_people = models.ForeignKey(People, related_name = 'to_people')
price = models.IntegerField()
def __unicode__(self):
return force_unicode(u'%s-%s-%s' % (self.from_people, self.to_people, self.price))


要实现的效果:在Buy的修改页面可以同时编辑from_people和to_people两个外键的值.
django admin页面的默认效果[img]http://dl.iteye.com/upload/picture/pic/74256/62c5f6b9-67b1-380a-9ed2-5a41a28e2919.jpg[/img]
需要的实现[img]http://fdayok.iteye.com/upload/picture/pic/74258/1bfee02d-de01-3a38-bf2d-82d843311313.jpg[/img]

django的帮忙文档中有通过TabularInline实现在修改People时同时修改Buy的方法,代码为

#admin.py
class BuyModelInline(djopt.TabularInline):
model = mym.Buy
fk_name = 'from_people'

class PeopleModelAdmin(djopt.ModelAdmin):
list_display = ['name']
inlines = [BuyModelInline]

效果:[img]http://fdayok.iteye.com/upload/picture/pic/74260/01ed03cb-5685-39b8-9846-df8d709dd242.jpg[/img]

查看了TabularInline的代码,发现可以实现一个从Buy到People反向外键内联类来达到目的.代码

#admin.py
from django.contrib.admin.util import flatten_fieldsets
from django.utils.functional import curry
import django.forms.models as djfmmdl
class ReverseFKTabularInline(djopt.TabularInline):
reverse_fk_name = None
def get_formset(self, request, obj = None, **kwargs):
"""Returns a BaseInlineFormSet class for use in admin add/change views."""
if self.declared_fieldsets:
fields = flatten_fieldsets(self.declared_fieldsets)
else:
fields = None
if self.exclude is None:
exclude = []
else:
exclude = list(self.exclude)
exclude.extend(kwargs.get("exclude", []))
exclude.extend(self.get_readonly_fields(request, obj))
# if exclude is an empty list we use None, since that's the actual
# default
exclude = exclude or None
defaults = {
"form": self.form,
"formset": self.formset,
"fk_name": self.reverse_fk_name,
"fields": fields,
"exclude": exclude,
"formfield_callback": curry(self.formfield_for_dbfield, request = request),
"extra": self.extra,
"max_num": self.max_num,
"can_delete": self.can_delete,
}
defaults.update(kwargs)
return self.inlineformset_factory(self.model, self.parent_model, **defaults)

def inlineformset_factory(self, model, model_has_fk, form = djfmmdl.ModelForm,
formset = djfmmdl.BaseInlineFormSet, fk_name = None,
fields = None, exclude = None,
extra = 3, can_order = False, can_delete = True, max_num = None,
formfield_callback = lambda f: f.formfield()):
"""
Returns an ``InlineFormSet`` for the given kwargs.

You must provide ``fk_name`` if ``model`` has more than one ``ForeignKey``
to ``model_has_fk``.
"""
fk = djfmmdl._get_foreign_key(model, model_has_fk, fk_name = fk_name)
# enforce a max_num=1 when the foreign key to the parent model is unique.
if fk.unique:
max_num = 1
kwargs = {
'form': form,
'formfield_callback': formfield_callback,
'formset': formset,
'extra': extra,
'can_delete': can_delete,
'can_order': can_order,
'fields': fields,
'exclude': exclude,
'max_num': max_num,
}
FormSet = djfmmdl.modelformset_factory(model, **kwargs)
FormSet.fk = fk
return FormSet


上面是基类,下面实现People内联类

#admin.py
class PeopleTabularInline(ReverseFKTabularInline):
model = mym.People
extra = 0
class SalerInline(PeopleTabularInline):
reverse_fk_name = 'from_people'
verbose_name_plural = 'Saler'
class BuyerInline(PeopleTabularInline):
reverse_fk_name = 'to_people'
verbose_name_plural = 'Buyer'


内联类的使用方法

#admin.py
class BuyModelAdmin(djopt.ModelAdmin):
saler_name = make_func(mym.Buy, 'from_people__name')
buyer_name = make_func(mym.Buy, 'to_people__name')
list_display = [saler_name, buyer_name, 'price']
readonly_fields = [saler_name]
inlines = [SalerInline, BuyerInline]


完成后的效果[img]http://fdayok.iteye.com/upload/picture/pic/74262/c472169a-9acc-35be-ae77-2f96b77971c8.jpg[/img]
图中红框里的显示是readonly_fields = [saler_name]这行代码的结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值