0
votes

please help a beginner. I'm trying to build a poll app in Django and I want to change my admin panel so that I can change and add questions and choices in the same page iv already tried to create a new model and bind the question and choice model together but didn't work please help me. this is my models.py inside my poll app and another problem I have is that I want to have different numbers of choices for different questions but I don't know how to write

from django.db import models

# Create your models here.
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text
class Bind(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')    
    add_question =Question(question_text=question_text,pub_date=pub_date)

    choice_text_1= models.CharField(max_length=200,default='yes')
    votes_1= models.IntegerField(default=0)
    choice_text_2= models.CharField(max_length=200,default='yes')
    votes_2= models.IntegerField(default=0)
    choice_text_3= models.CharField(max_length=200,default='yes')
    votes_3= models.IntegerField(default=0)
    choice_text_4= models.CharField(max_length=200,default='yes')
    votes_4= models.IntegerField(default=0)
    add_choice1=Choice(choice_text=choice_text_1,votes=votes_1)
    add_choice2=Choice(choice_text=choice_text_2,votes=votes_2)
    add_choice3=Choice(choice_text=choice_text_3,votes=votes_3)
    add_choice4=Choice(choice_text=choice_text_4,votes=votes_4)
    def __str__(self):

        return self.question_text 
        return self.choice_text

and this is my admin panel id like to change it that I can add question with different number of choices and when I save I can find save question in question model pannel and choices in the choice model panel please help me I'm a beginner enter image description here

and this is views.py file:

class IndexView(generic.ListView):
  template_name = 'polls/index.html'
  context_object_name = 'latest_question_list'
  def get_queryset(self):
    return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
  model = Question
  template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
  model = Question
  template_name = 'polls/results.html'
def vote(request, question_id):
 question = get_object_or_404(Question, pk=question_id)
 try:
  selected_choice = question.choice_set.get(pk=request.POST['choice'])
 except (KeyError, Choice.DoesNotExist):

  return render(request, 'polls/detail.html', {'question': question,'error_message': "You didn't select a choice.",})
 else:
  selected_choice.votes += 1
  selected_choice.save()

  return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

and the error by executing the python manage.py migrate

C:\projects\AM\FM\mysite>python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying polls.0009_auto_20200914_1002...Traceback (most recent call last):
File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init_.py", line 1774, in get_prep_value return int(value) ValueError: invalid literal for int() with base 10: 'choice'

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "manage.py", line 22, in main() File "manage.py", line 18, in main execute_from_command_line(sys.argv) File "C:\projects\AM\FM\lib\site-packages\django\core\management_init_.py", line 401, in execute_from_command_line utility.execute() File "C:\projects\AM\FM\lib\site-packages\django\core\management_init_.py", line 395, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py", line 330, in run_from_argv self.execute(*args, **cmd_options) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py", line 371, in execute output = self.handle(*args, **options) File "C:\projects\AM\FM\lib\site-packages\django\core\management\base.py", line 85, in wrapped res = handle_func(*args, **kwargs) File "C:\projects\AM\FM\lib\site-packages\django\core\management\commands\migrate.py", line 243, in handle post_migrate_state = executor.migrate( File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial) File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_forwards state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial) File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\executor.py", line 227, in apply_migration state = migration.apply(state, schema_editor) File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\migration.py", line 124, in apply operation.database_forwards(self.app_label, schema_editor, old_state, project_state) File "C:\projects\AM\FM\lib\site-packages\django\db\migrations\operations\fields.py", line 104, in database_forwards schema_editor.add_field( File "C:\projects\AM\FM\lib\site-packages\django\db\backends\sqlite3\schema.py", line 328, in add_field self.remake_table(model, create_field=field) File "C:\projects\AM\FM\lib\site-packages\django\db\backends\sqlite3\schema.py", line 189, in remake_table self.effective_default(create_field) File "C:\projects\AM\FM\lib\site-packages\django\db\backends\base\schema.py", line 303, in effective_default return field.get_db_prep_save(self.effective_default(field), self.connection) File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields\related.py", line 971, in get_db_prep_save return self.target_field.get_db_prep_save(value, connection=connection) File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py", line 823, in get_db_prep_save return self.get_db_prep_value(value, connection=connection, prepared=False) File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py", line 2388, in get_db_prep_value value = self.get_prep_value(value) File "C:\projects\AM\FM\lib\site-packages\django\db\models\fields_init.py", line 1776, in get_prep_value raise e.class( ValueError: Field 'id' expected a number but got 'choice'.

2

2 Answers

0
votes

You cannot directly assign other models to other model's fields. You have to use either ForeignKey (One Object To Many Referrable Objects) or ManyToManyField (Many Objects Can Be Contained To This Object).

At this point, you might want to consider making class Bind to class Questionnaire since you're combining them.

With that, with fixes applied and redundancies, this should be the final code (for inheritances only!)


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    question_choices = models.ForeignKey("Choice", on_delete=models.CASCADE)
    pub_date = models.DateTimeField(help_text='date published', auto_now_add=True)
    def __str__(self):
        return self.question_text

# No need to refer to the `Question` Model unless you have something to do important.
# Cross-Reference is okay, but its redundant unless special handling is required (for instance, you want pure integrity of ownership of this object, etc. But its quite hard to manage if your models were scaling.)
class Choice(models.Model):
    # question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    def __str__(self):
        return self.choice_text

class Questionnaire(models.Model):
    questions = models.ManyToManyField("Question", blank=True)
    pub_date = models.DateTimeField(help_text='date published', auto_now_add=True)    

    def __str__(self):
        return self.question_text 

NOTES:

  1. If you read the changes closely, you might see yourself, why I assigned the object in "str" form? That's because Django was able to load objects, even or after the one who requires it. Meaning, You don't need to put another object on the top to refer at, but rather, just put it in str reference even the object is placed anywhere and you're good to go.

  2. Note that in DateTimeField, you would want to consider auto_now_add=True, it automatically handles the time where this object has been saved for the first time.

  3. I want to make all choices under Question. This would be nice because if you want to make a question, there's a field available for you to create a choice to.

  4. I changed Bind with Questionnaire for clarity. This should be enough to see the relationship or inheritance to your model.

  5. I used ManyToManyField to set number of questions (or objects) to this Questionnaire.

0
votes

Usually, in such cases, you don't need to create "Bind" model. You just need to add "sequence" integer field into your Choice model. Then, each question can have infinite number of choices, for example:

Choice.objects.create(question=question1, sequence=0)
Choice.objects.create(question=question1, sequence=1)
Choice.objects.create(question=question1, sequence=2)...