在管理员的内联表单中限制外键选择 [英] Limit foreign key choices in select in an inline form in admin

查看:352
本文介绍了在管理员的内联表单中限制外键选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

模型的逻辑是:

  • 一个大楼有很多房间
  • 一个 Room 可能在另一个 Room 内(例如一个壁橱——'self' 上的 ForeignKey)
  • 一个 Room 只能在同一建筑物的另一个 Room 内(这是棘手的部分)
  • A Building has many Rooms
  • A Room may be inside another Room (a closet, for instance--ForeignKey on 'self')
  • A Room can only be inside another Room in the same building (this is the tricky part)

这是我的代码:

#spaces/models.py
from django.db import models    

class Building(models.Model):
    name=models.CharField(max_length=32)
    def __unicode__(self):
        return self.name

class Room(models.Model):
    number=models.CharField(max_length=8)
    building=models.ForeignKey(Building)
    inside_room=models.ForeignKey('self',blank=True,null=True)
    def __unicode__(self):
        return self.number

和:

#spaces/admin.py
from ex.spaces.models import Building, Room
from django.contrib import admin

class RoomAdmin(admin.ModelAdmin):
    pass

class RoomInline(admin.TabularInline):
    model = Room
    extra = 2

class BuildingAdmin(admin.ModelAdmin):
    inlines=[RoomInline]

admin.site.register(Building, BuildingAdmin)
admin.site.register(Room)

内联将仅显示当前建筑物中的房间(这是我想要的).但问题在于,对于 inside_room 下拉菜单,它会显示 Rooms 表中的所有房间(包括其他建筑物中的房间).

The inline will display only rooms in the current building (which is what I want). The problem, though, is that for the inside_room drop down, it displays all of the rooms in the Rooms table (including those in other buildings).

rooms 的内联中,我需要将 inside_room 选项限制为仅位于当前 building<中的 rooms/code>(当前由 BuildingAdmin 主窗体更改的建筑记录).

In the inline of rooms, I need to limit the inside_room choices to only rooms which are in the current building (the building record currently being altered by the main BuildingAdmin form).

我无法找到使用模型中的 limit_choices_to 的方法,也无法弄清楚如何正确覆盖管理员的内联表单集(我觉得我应该以某种方式创建一个自定义内联表单,将主表单的 building_id 传递给自定义内联,然后基于此限制字段选择的查询集——但我就是不知道该怎么做).

I can't figure out a way to do it with either a limit_choices_to in the model, nor can I figure out how exactly to override the admin's inline formset properly (I feel like I should be somehow create a custom inline form, pass the building_id of the main form to the custom inline, then limit the queryset for the field's choices based on that--but I just can't wrap my head around how to do it).

也许这对于管理站点来说太复杂了,但它似乎通常很有用......

Maybe this is too complex for the admin site, but it seems like something that would be generally useful...

推荐答案

使用请求实例作为 obj 的临时容器.重写内联方法 formfield_for_foreignkey修改查询集.这至少适用于 django 1.2.3.

Used request instance as temporary container for obj. Overrided Inline method formfield_for_foreignkey to modify queryset. This works at least on django 1.2.3.

class RoomInline(admin.TabularInline):

    model = Room

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):

        field = super(RoomInline, self).formfield_for_foreignkey(db_field, request, **kwargs)

        if db_field.name == 'inside_room':
            if request._obj_ is not None:
                field.queryset = field.queryset.filter(building__exact = request._obj_)  
            else:
                field.queryset = field.queryset.none()

        return field



class BuildingAdmin(admin.ModelAdmin):

    inlines = (RoomInline,)

    def get_form(self, request, obj=None, **kwargs):
        # just save obj reference for future processing in Inline
        request._obj_ = obj
        return super(BuildingAdmin, self).get_form(request, obj, **kwargs)

这篇关于在管理员的内联表单中限制外键选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆