簡體   English   中英

Django管理員:通過非相鄰的ManyToMany關系使用內聯

[英]Django admin: using inlines through a non-adjacent ManyToMany relationship

考慮以下models.py ,其中一個組包含多個具有零個或多個電話號碼的人。 在這種情況下,共享一個群組的人通常會共享至少一個電話號碼,因此使用了多對多關系。

class Group(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    group = models.ForeignKey(Group)
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

class Phone(models.Model):
    persons = models.ManyToManyField(Person)
    number = models.CharField(max_length=30)

我想在Django管理員中以單一視圖顯示這些模型,如下所示。

class PersonInline(admin.StackedInline):
    model = Person

class PhoneInline(admin.StackedInline):
    model = Phone # also tried: Phone.persons.through

@admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
    inlines = [PersonInline, PhoneInline]

但是,Group和Phone之間沒有外鍵,因此會引發SystemCheckError (以下之一):
<class 'myapp.admin.PhoneInline'>: (admin.E202) 'myapp.Phone' has no ForeignKey to 'myapp.Group'.
<class 'myapp.admin.PhoneInline'>: (admin.E202) 'myapp.Phone_persons' has no ForeignKey to 'myapp.Group'.

是否可以通過“人”模型來完成這項工作? 電話內聯的目標是顯示組中所有人員的電話號碼記錄(獎金:添加新電話時,Person SelectMultiple小部件將只需要顯示組中其他人員)。 我寧願避免修改任何模板。 如有必要,可以集成第三方應用程序。 我可以使用Django 1.10或1.11。

謝謝!

我通過稍微修改需求來解決了這個問題。 我不是只要求在PhonePerson之間建立關系,而是添加了另一對多關系: PhoneGroup之間。 對於我的特殊情況,這種方法實際上效果更好。 Group應該在刪除時級聯到相關的Person和相關的Phone

問題中顯示的admin.py沒有變化。 models.pyPhone類中的另一行是ForeignKey字段:

class Phone(models.Model):
    group = models.ForeignKey(Group)
    persons = models.ManyToManyField(Person)
    number = models.CharField(max_length=30)

上面的“獎金”要求Person內聯中的ManyToManyField表單窗口小部件僅顯示同一Group中的Person 為此,可以將兩個函數添加到admin.py

class PersonInline(admin.StackedInline):
    model = Person

class PhoneInline(admin.StackedInline):
    model = Phone

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
        field = super(PhoneInline,
                      self).formfield_for_manytomany(db_field, request,
                                                     **kwargs)
        if db_field.name == 'persons':
            if request._obj_ is None:
                field.queryset = field.queryset.none()
            else:
                qs = Person.objects.filter(group=request._obj_.id)
                field.queryset = qs
                field.initial = qs
        return field

@admin.register(Group)
class GroupAdmin(admin.ModelAdmin):
    inlines = [PersonInline, PhoneInline]

    def get_form(self, request, obj=None, **kwargs):
        # Save obj reference for future processing in Phone inline
        request._obj_ = obj
        return super(GroupAdmin, self).get_form(request, obj, **kwargs)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM