Django 在后台反向外键
我有一个关于Django的管理面板中外键的问题。我的情况是这样的:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver)
class DriverAssignment(models.Model):
device = models.ForeignKey(Device)
driver = models.ForeignKey(Driver)
每个设备都需要绑定一个驱动程序(也就是它使用的那个)。DriverAssignment应该是一个表,显示哪个驱动程序可以被哪个设备使用。所以一个设备可以绑定多个可能的驱动程序。现在我想在我的管理面板上有一个下拉菜单,显示特定设备所有可能的驱动程序,以便选择'绑定的驱动程序'。
我该如何在Django中实现这个功能呢?这对一个有经验的Django开发者来说可能很简单。我希望有人能给我一点提示,因为我对Django还比较陌生。非常感谢!
3 个回答
这里有一个关于反向内联的代码片段。如果你还需要,可以试试这个链接:https://gist.github.com/mzbyszewska/8b6afc312b024832aa85
我在使用django 1.5和1.6时,用过这个代码片段来处理OneToOneField。遗憾的是,我没有测试过ForeignKeyField,不过之前有用户说这个代码片段也适用于ForeignKeyField。
这个代码片段的最佳描述就在它里面。Person类对应你的DriverAssignment类,而Device则对应下面示例中的Address类:
Example:
from django.db import models
class Address(models.Model):
street = models.CharField(max_length = 255)
zipcode = models.CharField(max_length = 10)
city = models.CharField(max_length = 255)
class Person(models.Model):
name = models.CharField(max_length = 255)
business_addr = models.ForeignKey(Address,
related_name = 'business_addr')
home_addr = models.OneToOneField(Address, related_name = 'home_addr')
other_addr = models.OneToOneField(Address, related_name = 'other_addr')
You use reverseadmin in the following way:
from django.contrib import admin
from django.db import models
from models import Person
from reverseadmin import ReverseModelAdmin
class AddressForm(models.Form):
pass
class PersonAdmin(ReverseModelAdmin):
inline_type = 'tabular'
inline_reverse = ('business_addr', ('home_addr', AddressForm), ('other_addr' (
'form': OtherForm
'exclude': ()
)))
admin.site.register(Person, PersonAdmin)
inline_type can be either "tabular" or "stacked" for tabular and
stacked inlines respectively.
对于Django版本大于1.8的情况
可以使用InlineModelAdmin,具体的说明可以在那儿找到:
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
admin.py
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
把你的 模型结构改成这样:
class Driver(models.Model):
name = models.CharField(max_length=200)
executable = models.CharField(max_length=200)
class Device(models.Model):
name = models.CharField(max_length=200)
bound_driver = models.ForeignKey(Driver, related_name="bound_to")
available_drivers = models.ManyToManyfield(Driver)
ManyToManyField 可以替代 DriverAssignment 表,完成同样的工作。
你可以在可用司机字段中添加可用的司机。
但你也希望 bound_driver 是可用司机之一。 这个验证你需要在表单中进行。为此,你需要重写管理界面的表单。可以参考下面的链接。
参考链接:
ManytoMany 字段: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField
模型管理(重写管理功能): https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects
如果你想学得更多,就得花点时间阅读和实现这些内容。:)
或者
如果你想保持相同的结构,那么你需要重写 form
在 ModelAdmin
中,具体可以查看 这里,并提供你自己的表单,格式大概是这样的:
class CustomForm(ModelForm)
bound_driver = forms.ModelChoiceField(queryset = <your custom queryset that returns only available drivers>, ...)
class Meta:
model = Device
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form