title: How to CRUD ContentType in Django admin site?
body: <p>I'm reading a book about Django and I'm trying to reinterpret some content. (I'm using Django 2.1 and Python 3.6)
  In the book different types of contents are associated with a module, like this:</p>
  
  <pre><code>class Module(models.Model):
      course = models.ForeignKey(Course,
                          related_name='modules',
                          on_delete=models.CASCADE)
      title = models.CharField(max_length=200)
      description = models.TextField(blank=True)
      order = OrderField(blank=True, for_fields=['course'])
  
      class Meta:
          ordering = ['order']
  
      def __str__(self):
          return '{}. {}'.format(self.order, self.title)
  
  class Content(models.Model):
      module = models.ForeignKey(Module,
                          related_name='contents',
                          on_delete=models.CASCADE)
      content_type = models.ForeignKey(ContentType,
                                  on_delete=models.CASCADE,
                                  limit_choices_to={'model__in': (
                                      'text',
                                      'video',
                                      'image',
                                      'file')})
      object_id = models.PositiveIntegerField()
      item = GenericForeignKey('content_type', 'object_id')
      order = OrderField(blank=True, for_fields=['module'])
  
      class Meta:
          ordering = ['order']
  
  class ItemBase(models.Model):
      owner = models.ForeignKey(User,
                          related_name='%(class)s_related',
                          on_delete=models.CASCADE)
      title = models.CharField(max_length=250)
      created = models.DateTimeField(auto_now_add=True)
      updated = models.DateTimeField(auto_now=True)
  
      class Meta:
          abstract = True
  
      def __str__(self):
          return self.title
  
      def render(self):
          return render_to_string(
               'courses/content/{}.html'.format(self._meta.model_name),
               {'item': self})
  
  class Text(ItemBase):
      content = models.TextField()
  
  class File(ItemBase):
      file = models.FileField(upload_to='files')
  
  class Image(ItemBase):
      file = models.FileField(upload_to='images')
  
  class Video(ItemBase):
      url = models.URLField()
  </code></pre>
  
  <p>In the book there are CBVs to generate the right form for content types:</p>
  
  <pre><code>class ContentCreateUpdateView(TemplateResponseMixin, View):
      module = None
      model = None
      obj = None
      template_name = 'courses/manage/content/form.html'
  
      def get_model(self, model_name):
          if model_name in ['text', 'video', 'image', 'file']:
              return apps.get_model(app_label='courses',
                                  model_name=model_name)
          return None
  
      def get_form(self, model, *args, **kwargs):
          Form = modelform_factory(model, exclude=['owner',
                                               'order',
                                               'created',
                                               'updated'])
          return Form(*args, **kwargs)
  
      def dispatch(self, request, module_id, model_name, id=None):
          self.module = get_object_or_404(Module,
                                     id=module_id,
                                     course__owner=request.user)
          self.model = self.get_model(model_name)
          if id:
              self.obj = get_object_or_404(self.model,
                                       id=id,
                                       owner=request.user)
          return super(ContentCreateUpdateView,
             self).dispatch(request, module_id, model_name, id)
  
      def get(self, request, module_id, model_name, id=None):
          form = self.get_form(self.model, instance=self.obj)
          return self.render_to_response({'form': form,
                                      'object': self.obj})
  
      def post(self, request, module_id, model_name, id=None):
          form = self.get_form(self.model,
                           instance=self.obj,
                           data=request.POST,
                           files=request.FILES)
          if form.is_valid():
              obj = form.save(commit=False)
              obj.owner = request.user
              obj.save()
              if not id:
                  # new content
                  Content.objects.create(module=self.module,
                                     item=obj)
              return redirect('module_content_list', self.module.id)
          return self.render_to_response({'form': form,
                                          'object': self.obj})
  </code></pre>
  
  <p>And contents are provided by users with special permissions.
  Ok and now the question: I want the contents to be managed only by the admin, in the admin site.
  I've tried this way:</p>
  
  <pre><code>class ContentInline(GenericStackedInline):
      model = Content
      extra = 0
  
  @admin.register(Module)
  class ModuleAdmin(admin.ModelAdmin):
      list_display = ['title', 'order', 'course']
      list_filter = ['course']
      search_fields = ['title', 'description']
      inlines = [ContentInline]
  
  @admin.register(Content)
  class ContentAdmin(admin.ModelAdmin):
      list_display = ['object_id', 'module', 'content_type', 'order']
  </code></pre>
  
  <p>but I have not been able to display in the admin site forms the field to upload the right content type.
  Module page looks like this:</p>
  
  <p><a href="https://i.stack.imgur.com/KuYbi.png" rel="nofollow noreferrer">module page in admin site</a></p>
  
  <p>While Content page is this:</p>
  
  <p><a href="https://i.stack.imgur.com/hg6Ql.png" rel="nofollow noreferrer">content page in admin site</a></p>
  
  <p>I've been searching for a solution for a while but I've not been able to find one. There is a similar topic here: <a href="https://stackoverflow.com/questions/13907211/genericforeignkey-and-admin-in-django">link</a> but suggested solutions imply javascript and/or additional packages while I'd like to do that only with Python and Django.
  I've also read that a possible solution to display custom views in admin site is to write a view and then add it to the admin urls, then add it to the admin model.
  Someone else suggested to use CBV from the book and use it in model admin.
  I've tried to implement these suggestions with no luck.
  In the last version of my code I try to use the CBV with <code>as_view()</code> this way (in views.py right after CBV):</p>
  
  <pre><code>content_create_update_view = ContentCreateUpdateView.as_view()
  </code></pre>
  
  <p>and then in admin.py:</p>
  
  <pre><code>@admin.register(Content)
  class ContentAdmin(admin.ModelAdmin):
      list_display = ['object_id', 'module', 'content_type', 'order']
  
      def get_urls(self):
          urls = super().get_urls()
          my_urls = [
              path('content/&lt;int:object_id&gt;/change/', self.admin_site.admin_view(content_create_update_view)),
          ]
          return my_urls + urls
  </code></pre>
  
  <p>any help or suggestion is greatly appreciated.</p>