Django在管理员中反转外键

时间:2014-05-02 12:55:06

标签: python django django-models django-admin

我在管理面板中有关于外键的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应该是显示哪个驱动程序可以由哪个设备使用的表。因此,一个设备可以有多种可以绑定的驱动程序。现在我想在我的管理面板上有一个下拉列表,显示特定设备的所有可能驱动程序,以选择' bound_driver'。

我怎样才能在Django中这样做?对于经验丰富的Django人来说,这可能是件容易的事。我希望有人可以给我一个提示,因为我对Django有点新意。非常感谢!

3 个答案:

答案 0 :(得分:2)

模型结构更改为This:

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 Table相同的工作。

您可以在“可用的驱动程序”字段中添加“可用的驱动程序”。

但是你还希望bind_driver是可用的驱动程序之一。您必须在表单中进行此验证。为此,您必须覆盖Admin表单。见链接

参考链接:

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 ,请参阅here并提供自定义表单,这将类似于这样:

{{1}}

https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form

答案 1 :(得分:2)

对于Django&gt; 1.8

使用InlineModelAdmin(2.2的文档),如下所述:

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,
    ]

答案 2 :(得分:1)

有反向内联的片段。如果你仍然需要它,你可以试试这个: 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.