1

So I am trying to learn django and following this tutorial: https://docs.djangoproject.com/en/1.10/intro/tutorial01/

After following the tutorial and made the poll app, when I look back and look into the code, I just don't see where does this "question_id" come from. It doesn't appear when creating model.

Here are the codes for models:

from django.db import models
from django.utils import timezone
import datetime
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    def __str__(self):
        return self.question_text
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

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

And here in view.py:

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.http import Http404
from django.template import loader
from django.urls import reverse
from django.views import generic

from .models import Question
from .models import Choice
from django.utils import timezone

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,)))

question_id just appear from nowhere.

  1. Is it the case that when creating a model, django will automatically create a model_id for each instance?

  2. Also, another question is why they do "pk=question_id" and use pk thereafter. Does it matter?

codes in urls.py:

from django.shortcuts import render
from django.conf.urls import url

from . import views

app_name = 'polls'

urlpatterns = [
    # ex: /polls/
    url(r'^$', views.IndexView.as_view(), name='index'),
    # ex: /polls/5/
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(),     name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
 ]
  1. Additionally, when using generic view like this:

    class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html'

Could we pass in arguments (like question_id)?

Hansong Li
  • 417
  • 2
  • 11
  • 26
  • 1
    question_id is not part of the model, it is the parameter being passed into the view from the url. – Daniel Roseman Aug 11 '16 at 21:44
  • Note the last URL pattern, where you essentially define the name of the parameter through the pattern: `url(r'^(?P[0-9]+)/vote/$'`. And the you have `def vote(self, question_id)`, where the parameter matches the definition in the URL pattern. –  Aug 11 '16 at 21:47

3 Answers3

2

In your urlpatterns list in urls.py you have this route:

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote')

The url is actually a regex, so one string to specify a whole family of urls.
The question_id is a named part of the regex which defines a parameter of that url.

When the view, i.e. views.vote is called, the question_id parsed from the url is send in as a function argument.

For example, if a client visits the url:

 /123/vote/

Then the view function will be called like:

 vote(request=request, question_id=123)
  1. Is it the case that when creating a model, django will automatically create a model_id for each instance?

Yes.

  1. Also, another question is why they do "pk=question_id" and use pk thereafter. Does it matter?

Here pk stands for "primary key". It doesn't matter, really, the different names are only a scoping issue.

The function argument name for the vote view is "question_id". The function argument name inside of get_object_or_404 and question.choice_set.get methods is 'pk'.

They will just be different names pointing at the same object (the integer 123, for example).

wim
  • 338,267
  • 99
  • 616
  • 750
1
  1. Your statement is true you might want to take a look at the relevant Documentation for Django Models here: https://docs.djangoproject.com/en/1.10/topics/db/models/#automatic-primary-key-fields

Which notably states:

By default, Django gives each model the following field:

id = models.AutoField(primary_key=True)

This is an auto-incrementing primary key.

If you’d like to specify a custom primary key, just specify primary_key=True on one of your fields. If Django sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column.

Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

  1. You might also want to take a look at this question which briefly explains the different between ID's and Primary Keys in Django: What's the difference between Model.id and Model.pk in django?

  2. Why don't you try it and see ;)

Community
  • 1
  • 1
Jack Evans
  • 1,697
  • 3
  • 17
  • 33
0

As per your question, question_id is the field for the Choice table that you had created. If you look at the code carefully you may observe question= models.Foreignkey , this is the one which specifies that every entry in choice table is related to the every question in the Question table.

I will request you to run the below command

python manage.py sqlmigrate polls 0001

When you will observe the output it may specify the question_id field for the choice table thats indirectly corresponding to the id of Question table.

url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

So when the url like http://127.0.0.1:8000/polls/34/vote is parsed then The question_id='34' part comes from (?P[0-9]+). Using parentheses around a pattern “captures” the text matched by that pattern and sends it as an argument to the view function that we had created in views.py,the ?P defines the name that will be used to identify the matched pattern and [0-9]+ is a regular expression to match a sequence of digits (i.e., a number).

Also, we can say that question_id is the identifier for each and every entry in the table.

1.Is it the case that when creating a model, django will automatically create a model_id for each instance?

Yes django automatically assigns the unique id for each and every instance that is created