Question

I have questionnaire app that allows for the dynamic creation of a Form. In my current system I link it to a Project. Here is an example of my models. I want to separate the questionnaire app completely from dependencies of the other apps in my current django project.

#project.models
class Project(models.Model):
    name = models.CharField(max_length.....
    category = models.CharField(max_length
    question_sets = models.ManyToManyField(Question_Set)

#questionnaire.models
class Question(models.Model):
    question = models.CharField(max_length....
    question_type = models.IntegerField(choices=.....

class Question_set(models.Model):
    name = models.CharField(....
    questions = models.ManyToManyField(Question)

Inside my questionnaire.views, for this example, Ihave two basic functions Question_set create and Question create. In the Question_set create function I have a form that allows me to add created Questions to the Question_set and then save the Question_set. Currently I also pass the project_id in the url to this view so I can get the Project instance and add the Question_set

#questionnaire.views
def question_set_create(request, project_id, form_class=AddSetForm, template_name=....):
    if request.method = "POST":
        form = form_class(request.POST)
        if form.is_valid():
            set = form.save()
            project = Project.objects.get(id=project_id)
            project.question_sets.add(set)
            ....

#questionnaire.urls
#pattern for question_set_create
url(r'^(?P<project_id>[-\w]+)/add_set/$', 'questionnaire_create' , name="project_questionnaire_create"),

I believe the solution involves the Django ContentType Framework but I am not sure the best way to go about passing the model class via the url. So if the Question_set was to be saved to Foo model instead of Project. How in the url would I identify the model class?

Was it helpful?

Solution

I think the problem may be in the way you've organized your models. I would also avoid the use of a model name ending in _set as that could get very confusing. What about this instead:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from questionnaire.models import Questionnaire

#project.models
class Project(models.Model):
    name = models.CharField(max_length.....
    category = models.CharField(max_length
    questionnaires = generic.GenericRelation(Questionnaire)

#questionnaire.models
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Question(models.Model):
    question = models.CharField(max_length....
    question_type = models.IntegerField(choices=.....

class Questionnaire(models.Model):
    name = models.CharField(...)
    questions = models.ManyToManyField(Question)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey()

Once you have clearly defined the questionnaire as its own complete model, creating a URL becomes more straightforward:

#questionnaire.urls
#pattern for question_set_create
url(r'^(?P<content_type>[-\w]+)/(?P<object_id>[-\w]+)/add_set/$', 'questionnaire_create' , name="questionnaire_create"),

Where content_type is the name of the content type (say, 'projects.project' or something similar) and object_id is the primary key of the matching record.

So the equivalent URL for creating a questionnaire for project id #1 would be /questionnaires/projects.project/1/add_set/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top