Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Mike Nedelko
Mike Nedelko
8,991 Points

course_id in def step_detail()

When we define the step_detail we add the attributes course_id=course_pk as well as the attribute pk=step_pk

def step_detail(request, course_pk, step_pk): step = get_object_or_404(Step, course_id=course_pk, pk=step_pk) return render(request, 'courses/step_detail.html', {'step': step})

I know this was eluded to in the video but I want to confirm where the 'course_id' comes from. Is this the 'id' field in the course model which Django automatically generates without us askin Django to do so?

If so is there also a "step_id"?

I am asking because I do understand where the course_pk and the step_pk are coming from, I also understand that the 'pk' itself is something Django knows how to work with and I know that course_id is refering to the Foreigh Key field, but the format of the this field 'course_id' seems to be out of the ordinary for python. If this was automatically generated by Django, wouldn't this be Courses.course.id?

Any advice would be highly appreciated.

Mike

4 Answers

Hi Mike,

Thanks for sharing the code. It makes it easier to discuss things. You are on the right track with looking into black magic name mangling done by the framework. It is actually Django that modifies some identifiers such as 'course' to 'course_id'.

The apparent name change has to do with how Django does field lookup, which is documented here. There you'll find the following paragraph:

The field specified in a lookup has to be the name of a model field. There’s one exception
though, in case of a ForeignKey you can specify the field name suffixed with _id. In this
case, the value parameter is expected to contain the raw value of the foreign model’s primary key.

Your question of 'id' vs 'pk' is also related to field lookup. 'pk' is a Django shortcut to an exact match lookup of a model's primary key, which in the default case (when Django automatically generates the primary key for a model) is called 'id'. Check out the documentation of this feature here.

I hope this answers your questions.

Hey Mike,

course_id is the field name in the Step model. It is a foreign key to the Course model, and as such it's value holds a reference to a specific Course model instance (the one to which this step belongs). This reference points to a unique id field value, which id was automatically generated by Django for the Course model as you mentioned.

To answer your question, there is no step_id, because the foreign key relationship of Step.course_id -> Course.id allows querying the relationship between Step and Course both ways using the course_id filed in Step. For details, see this in the Django documentation.

In fact, having a one-to-many relationship in both directions between two models is a violation of database design rules, because it introduces potential ambiguity in references between the models. Therefore, there should be no step_id in the example you refer to.

Cheers!

Mike Nedelko
Mike Nedelko
8,991 Points

Hi Attila

Thank you for your answer. It is vry coherent and makes sense. The only thing I remain confused about is where the name for the field 'course_id' (name beeing 'course_id') comes from.

I can't seem to find a field names 'course_id' in either of the models we defined in models.py.

class Course(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    title = models.CharField(max_length=255)
    description = models.TextField()

    def __str__(self):
        return self.title


class Step(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField()
    content = models.TextField(blank=True, default='')
    order = models.IntegerField(default=0)
    course = models.ForeignKey(Course)

--> What confuses me is that none of these variables inside the functions is called course_id.

The first time 'course_id' appears is in the views.py definition of step_detail.

step = get_object_or_404(Step, course_id=course_pk, pk=step_pk)

How does Django know that course_id references the Foreign Key field? In our model the ForeignKey is assigned to the variable 'course' not 'course_id'.

course = models.ForeignKey(Course)

I guess the question I have might be related to how the object's get method [Course.objects.get(pk=pk)] would looke like if we expanded the get_object_or_404 shortcut inside the step_detail function.

From what I understand, Django magically seems to know that 'pk' automatically relates to the model's ID field by way of convention that was programmed into how Django interprets the code. Is this the same case for course_id? Did Django automatically name this field course_id without us having to do so? If so, is there any documentation that lists this and other conventions like it?

My apologies for being so confused about this and thank you very much for your kind support. Mike

Mike Nedelko
Mike Nedelko
8,991 Points

ADDITION: So I feel I might have found a solution for my question but would require confirmation to see if I am on the right track here:

It seems like the field name 'course_id' does not arise from Django but more from the way SQL's naming conventions work, is that correct?

So if I have the field name 'course' (which we defined in the Step model) and the ForeignKey field's name was titled ID, I need to use course_id to point to that Foreign Key field.

If the field name was 'post' (in a chat program for example) and the ForeignKey field was titled 'chatid', I needed to use post_chatid to point to the Foreign Key field (in this example one chat window can contain many posts; so 1:n).

Is that about right?