简体   繁体   English

Django反向管理员外键

[英]Django reverse foreign key in admin

I have a Django related question about foreign keys in the admin panel. 我在管理面板中有一个关于外键的Django相关问题。 I'm facing the following situation: 我面临以下情况:

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)

Every device needs to have a bound driver (which it uses). 每个设备都需要有一个绑定的驱动程序(它使用)。 DriverAssignment should be the table which shows which driver can be used by which device. DriverAssignment应该是显示哪个驱动程序可以被哪个设备使用的表。 So one device can have multiple possibilities of drivers which can be bound. 因此,一台设备可以具有多种可以绑定的驱动程序。 Now i would like to have a dropdown on my admin panel showing all possible drivers for a specific device to select the 'bound_driver'. 现在,我想在管理面板上显示一个下拉列表,显示特定设备的所有可能驱动程序,以选择“ bound_driver”。

How can i do this in Django? 如何在Django中执行此操作? This is probably an easy thing for an experienced Django guy. 对于有经验的Django家伙来说,这可能是一件容易的事。 I hope someone can give me a hint since i'm kind of new to Django. 我希望有人能给我一个提示,因为我是Django的新手。 Thanks a lot! 非常感谢!

For Django >1.8 对于Django> 1.8

Use the InlineModelAdmin (docs for 2.2) as explained there: 按照以下说明使用InlineModelAdmin (2.2版文档):

models.py 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 admin.py

from django.contrib import admin

class BookInline(admin.TabularInline):
    model = Book

class AuthorAdmin(admin.ModelAdmin):
    inlines = [
        BookInline,
    ]

Change your model Structure to 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 would do the same work as DriverAssignment Table. ManyToManyField将执行与DriverAssignment Table相同的工作。

You can add Available drivers in Available drivers field. 您可以在“可用驱动程序”字段中添加“可用驱动程序”。

But then You would also Want that bound_driver is one of the Available Drivers . 但是然后您还希望bound_driver是Available Drivers之一 This validation you will have to do in forms. 您必须以表格形式进行此验证。 For that you have to over-ride Admin forms. 为此,您必须重写管理表单。 See links 查看连结

Links of Reference: 参考链接:

ManytoMany field : https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField ManytoMany字段https : //docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ManyToManyField

Model Admin (to over-ride admin functionality) : https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects 模型管理员(以替代管理员功能)https : //docs.djangoproject.com/en/1.6/ref/contrib/admin/#modeladmin-objects

You will have to spend some time reading and implementing if you want ot learn more. 如果您想了解更多信息,则必须花一些时间阅读和实施。 :) :)

OR 要么

If you want to go with the same structure, than you will have to over-ride the form in ModelAdmin see here and Provide you custom form, which will be something like this: 如果要使用相同的结构,则必须覆盖ModelAdminform ,请参见此处并提供自定义表单,如下所示:

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 https://docs.djangoproject.com/en/1.6/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form

There is a snippet for inverse inlines. 反向内联有一个代码段。 If you still need it you may try this: https://gist.github.com/mzbyszewska/8b6afc312b024832aa85 如果仍然需要,可以尝试以下操作: https : //gist.github.com/mzbyszewska/8b6afc312b024832aa85

It has been used by me for OneToOneField in django 1.5 and 1.6. 我在Django 1.5和1.6中将它用于OneToOneField。 Unfortunately I did not test it for ForeignKeyField, but the one of the previous users claims that it works for ForeignKeyField either. 不幸的是,我没有针对ForeignKeyField对其进行测试,但是先前的用户之一声称它也适用于ForeignKeyField。

The best description of the snippet is contained in it. 其中包含对代码段的最佳描述。 The Person class is your DriverAssignment class and Device correspond to the Address class in the example below: 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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM