Django Admin通用内容类型多个模型内联形式

时间:2019-03-07 22:52:14

标签: python django django-contenttypes django-generic-relations

我刚开始使用Django,但在多模型字段AKA Generic Relation(内容类型)上还是有点困惑

我有一个通用的内容类型“ student_solution”,可以属于以下任一类型:

  • RepoB模型
  • Org模型
  • Institution模型

因此,在这三个模型的每个模型中,每个Campus的关系都相反,如下所示:

models.py
  

我不确定这是否是正确的方法,但是欢迎您确认:)


它现在可以正常工作,但是它在Django Admin UI中并不友好,请在创建学生解决方案时查看它在django admin上的显示方式(我希望选择框显示# Reverse generic relation - XXX See https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#reverse-generic-relations student_solutions = GenericRelation('student_solution.StudentSolution') 字段,而不是手动输入Content Type ID):

django admin create entity

在创建组织,机构或校园时,该字段在Django Admin中根本不会显示(因此我可能配置有误)

我尝试遵循How to replace content_type and object_id fields by a field with actual object in admin inline?来改进UI,方法是允许使用对象的标签选择正确的内容类型和“对象”。但这暂时不起作用。


label

student_solution/models.py

from django.contrib.contenttypes import fields from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import Q from jsonfield import JSONField from tfp_backoffice.apps.institution.models import Institution CONTENT_TYPE_CHOICES = ( Q(app_label='org', model='org') | Q(app_label='institution', model='institution') | Q(app_label='campus', model='campus') ) class StudentSolution(models.Model): # Dynamic relationship to either Org, Institution or Campus entities # XXX https://simpleisbetterthancomplex.com/tutorial/2016/10/13/how-to-use-generic-relations.html content_type = models.ForeignKey( ContentType, on_delete=models.CASCADE, # TODO check if good thing limit_choices_to=CONTENT_TYPE_CHOICES, ) object_id = models.PositiveIntegerField() content_object = fields.GenericForeignKey( 'content_type', 'object_id' )

student_solution/admin.py

from django.contrib import admin from modeltranslation.admin import TranslationAdmin from tfp_backoffice.apps.org.models import Org from tfp_backoffice.apps.student_solution.forms import StudentSolutionAdminForm, GenericStudentSolutionOwnerChoicesFieldForm from tfp_backoffice.apps.student_solution.models import StudentSolution class StudentSolutionInlineAdmin(admin.TabularInline): form = GenericStudentSolutionOwnerChoicesFieldForm model = Org # TODO not sure at all about that, should be either of 3 related ContentTypes (Org | Institution | Campus) # This throw error "<class 'tfp_backoffice.apps.student_solution.admin.StudentSolutionInlineAdmin'>: (admin.E202) 'org.Org' has no ForeignKey to 'student_solution.StudentSolution'." class StudentSolutionAdmin(TranslationAdmin): form = StudentSolutionAdminForm inlines = [ StudentSolutionInlineAdmin, ] admin.site.register(StudentSolution, StudentSolutionAdmin)

student_solution/forms.py

但是此代码不起作用,并且在启动服务器时抛出此错误

  

django.core.management.base.SystemCheckError:SystemCheckError:系统检查确定了一些问题:

     

from django import forms from django.contrib.contenttypes.models import ContentType from tfp_backoffice.apps.org.models import Org from tfp_backoffice.apps.student_solution.models import CONTENT_TYPE_CHOICES, StudentSolution class StudentSolutionAdminForm(forms.ModelForm): class Meta: model = StudentSolution fields = '__all__' # Keep all fields class GenericStudentSolutionOwnerChoicesFieldForm(forms.ModelForm): ct_place_type = ContentType.objects.get_for_model(Org) # TODO not sure at all about that, should be either of 3 related ContentTypes (Org | Institution | Campus) object_id = forms.ModelChoiceField( Org.objects.all(), limit_choices_to=CONTENT_TYPE_CHOICES, label='Student solution' ) content_type = forms.ModelChoiceField( ContentType.objects.all(), initial=ct_place_type, limit_choices_to=CONTENT_TYPE_CHOICES, # should I use this here? widget=forms.HiddenInput() ) def clean_object_id(self): return self.cleaned_data['object_id'].pk def clean_content_type(self): return self.ct_place_type

2 个答案:

答案 0 :(得分:1)

如果我了解您要正确执行的操作,则应该让StudentSolutionInlineAdminOrgInstitution的每个管理员都拥有Campus,并且应该GenericTabularInlinehttps://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations-in-admin)。

例如,您的org/admin.py中会有类似的内容:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline
from django import forms

from .models import Org
from student_solution.models import StudentSolution

class StudentSolutionInlineAdmin(GenericTabularInline):
    model = StudentSolution
    extra = 1

class StudentSolutionAdminForm(forms.ModelForm):
    class Meta:
        model = StudentSolution
        fields = '__all__'  # Keep all fields 

@admin.register(Org)
class OrgAdmin(admin.ModelAdmin):
    form = StudentSolutionAdminForm
    inlines = [StudentSolutionInlineAdmin]

这将允许您从Org管理员中添加与Org相关的StudentSolution。

答案 1 :(得分:0)

您可以看看以下内容:https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations-in-admin

如果您使用内容类型功能框架,则它们具有特殊的内联类型