I have a model called "Step" that is connected to a learning guide through a foreign key. In my views.py file I am simply querying the steps using this
learning_guides_steps = learning_guide.step_set.all()
and in the templates I am just looping through the steps using a for loop and displaying the title of the steps like this
{%for step in learning_guides_steps%}
<div >
<!-- Displaying the title of the step with an angle down button beside the title -->
<div class = "btn-group step" >
<a href = "#" class = "btn stepname" role = "button" style = "font-size: 18px;"> {{forloop.counter}}. {{step.title}}</a>
</div>
</div>
However when I display it in website its printing in reversed order. Can anyone explain why this is happening and how I can fix this? I am new to Django and Postgres, so any help would be appreciate it. Thank you. My Step model and the views is given below
class Step(models.Model):
title = models.CharField(max_length=200, null=False)
step_description = models.TextField(max_length=1000, null=False)
# enforces one-to-many relationship between LearningGuide and Step.
# Deleting a LearningGuide deletes all the associated steps (CASCADE delete)
learning_guide = models.ForeignKey(LearningGuide, on_delete=models.CASCADE)
class LearningGuide(models.Model):
title = models.CharField(null=False, max_length=50)
image = models.ImageField(upload_to='learning_guides_images/')
short_description = models.TextField(max_length=100, null=False)
category = models.ForeignKey(Category, on_delete=models.DO_NOTHING)
indicators = models.ManyToManyField(Indicator, blank=True)
external_resource = models.BooleanField(default=False, blank=True)
external_resource_link = models.URLField(null=True, blank=True)
My views.py file:
learning_guide = LearningGuide.objects.get(pk=learning_guide_id)
learning_guides_indicators = learning_guide.indicators.all()
indicators = Indicator.objects.all()
learning_guides_steps = learning_guide.step_set.all()
context = {
'learning_guide': learning_guide,
'indicators': indicators,
'learning_guides_indicators':learning_guides_indicators,
'learning_guides_steps':learning_guides_steps,
'homepage':False
}
CodePudding user response:
Option 1 (probably the easiest)
Order the queryresults in your view by using order_by:
learning_guides_steps = learning_guide.step_set.all().order_by('step__title')
# OR to order in the opposite direction,
learning_guides_steps = learning_guide.step_set.all().order_by('-step__title')
Note that I'm guessing you want to order by the title of the step, but you can order by any other field by just replacing title in the order_by, like order_by('step__pk')
if you want to order by the step's primary key. Note that the -
in each case reverses the direction. And note the double underscore between step and title step__title
because you are ordering by a ForeignKey.
Option 2 Set the default ordering on the model itself by using the class Meta:
class Step(models.Model):
title = models.CharField(max_length=200, null=False)
step_description = models.TextField(max_length=1000, null=False)
learning_guide = models.ForeignKey(LearningGuide, on_delete=models.CASCADE)
class Meta:
ordering = ['title']
# OR in the other direction
ordering = ['-title']
This will require you to run python manage.py makemigrations
and python manage.py migrate
Option 3
Add an order field to the step, and order by that. This way you can set the order, and not order alphabetically, or by an auto generated primary key:
class Step(models.Model):
title = models.CharField(max_length=200, null=False)
order = models.PositiveIntegerField(default=1)
step_description = models.TextField(max_length=1000, null=False)
learning_guide = models.ForeignKey(LearningGuide, on_delete=models.CASCADE)
class Meta:
ordering = ['order']
ordering = ['-order']
Note that this third option will also require you to run python manage.py makemigrations
and python manage.py migrate
. I've added the default value of 1 to the order so that this migration will not complain about a NULL value, but it means that ALL the Steps will have an order of 1 until you change it. There is a way around this, but I think this will work.