1

I have a Comment Model that uses ContentType and GenericForeignKey so that a comment can be attached to an instance of an arbitrary model:

class Comment(models.Model):
    ...
    text = models.TextField() 
    target_content_type = models.ForeignKey(ContentType, related_name='comment_target',
        null=True, blank=True)
    target_object_id = models.PositiveIntegerField(null=True, blank=True)
    target_object = GenericForeignKey("target_content_type", "target_object_id")

And I have a form for creating Comments:

class CommentForm(forms.Form):
    new_comment = forms.CharField(widget=forms.Textarea(attrs={'rows':2}))

The form is used like this:

  <form method="POST" action="{% url 'comments:create' %}">{% csrf_token %}
    {{ form | crispy }}
    <input type='hidden' name = 'target_id' value='{{q.id}}' />
    <input type='submit' class='btn btn-primary' value='Add reply' />
  </form>

In my Create view, how can I get the model of the originating object, or the ContentType & id, so that I can create a new Comment?

def comment_create(request):
    if request.method == "POST":
      if form.is_valid():
        text = form.cleaned_data.get('new_comment')  
        target_object_id = request.POST.get('target_id')
        target_content_type = ?
        ...
M.javid
  • 6,387
  • 3
  • 41
  • 56
43Tesseracts
  • 4,617
  • 8
  • 48
  • 94

1 Answers1

1

When you generate the form, add a hidden field that also includes the content type id.

From there you can then query the in-built Django ContentType model, like so:

from django.contrib.contenttypes.models import ContentType
my_model = ContentType.objects.get(id=some_id).model_class()

As for how to get the content type id in there, because you can't use methods that take arguments you can either change how your form is constructed (adding a hidden field and populating a default (better way) or creating a template tag that would act as a helper function to populate a hidden field in the html template (easier way).

In either case, you can then just use the ContentType again to call this:

ct = ContentType.objects.get_for_model(my_item)

Credit to this question.

Community
  • 1
  • 1