[英]Django Admin Generic content type multiple models inline form
I'm getting started with Django and I'm a bit stuck on a multi-models field, AKA Generic Relation (Content Type)我刚开始使用 Django,但在多模型领域(AKA Generic Relation(内容类型))上有点卡住了
I have a generic content type "student_solution" that can belong to either:我有一个通用的内容类型“student_solution”,它可以属于:
Org
model Org
模型Institution
model Institution
模式Campus
model Campus
模式Therefore, in each of those 3 models, I have a reversed relationship as follow, in each models.py
:因此,在这 3 个模型中的每一个中,我在每个
models.py
中都有如下相反的关系:
# Reverse generic relation - XXX See https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#reverse-generic-relations
student_solutions = GenericRelation('student_solution.StudentSolution')
I'm not sure whether this is the right approach, I think so, but a confirmation is welcome :)
我不确定这是否是正确的方法,我认为是这样,但欢迎确认:)
It's working fine as it is now, but it's not user-friendly in the Django Admin UI, see how it display on django admin, when creating a Student Solution (I would expect a select box showing a label
field, instead of entering the Content Type ID by hand):它现在工作正常,但它在 Django Admin UI 中不是用户友好的,看看它如何在 django admin 上显示,在创建学生解决方案时(我希望选择框显示
label
字段,而不是输入内容手动输入 ID):
When creating either an Org, Institution or Campus, the field doesn't show at all in the Django Admin (so I probably misconfigured something)创建组织、机构或校园时,该字段根本不显示在 Django 管理中(所以我可能配置错误)
I tried following How to replace content_type and object_id fields by a field with actual object in admin inline?我尝试了如何通过内联管理中的实际对象的字段替换 content_type 和 object_id 字段? to improve the UI by allowing to select the right Content Type and "object" using the object's label.
通过允许使用对象的标签选择正确的内容类型和“对象”来改进 UI。 But it doesn't work at this time.
但此时它不起作用。
student_solution/models.py
: 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
: 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
: student_solution/forms.py
:
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
But this code isn't working and throw this error when starting the server但是此代码不起作用并在启动服务器时抛出此错误
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
django.core.management.base.SystemCheckError: SystemCheckError: 系统检查发现了一些问题:
<class 'tfp_backoffice.apps.student_solution.admin.StudentSolutionInlineAdmin'>: (admin.E202) 'org.Org' has no ForeignKey to 'student_solution.StudentSolution'.
If I am understanding what you would like to do correctly you should have your StudentSolutionInlineAdmin
in each of the Org
, Institution
, and Campus
admins and it should be a GenericTabularInline
( https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations-in-admin ).如果我理解您想要正确执行的操作,您应该在每个
Org
、 Institution
和Campus
管理员中都有您的StudentSolutionInlineAdmin
,它应该是一个GenericTabularInline
( https://docs.djangoproject.com/en/2.2/ref/ contrib/contenttypes/#generic-relations-in-admin )。
So you would have something like this in (for example) your org/admin.py
:所以你会在(例如)你的
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]
This will allow you to add a StudentSolution related to an Org
from within the Org
admin.这将允许您从
Org
管理员中添加与Org
相关的 StudentSolution。
You could have a look on this one: https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations-in-admin你可以看看这个: https : //docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations-in-admin
They have special inline types to use if you are using the content type feature framework如果您使用的是内容类型功能框架,它们有特殊的内联类型可供使用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.