简体   繁体   中英

Transferring user input from one page to another

I am making a website that allows students to find upcoming study sessions for their courses. I am doing this in Django and HTML. A student uploads their courses to the site and they are shown on the courses page as buttons (ex. CS 101 - Intro to CS). When a student clicks on one of their courses (button), it is supposed to bring them to a page that shows available study sessions for that course. I am stuck because I do not know how to properly filter the available study sessions on the next page based on which course is clicked. Is there a way to store the info of the course as a variable so when the button is clicked I can use that variable to filter the results? EDIT: I have made these changes and now I am getting a ValueError too many values to unpack expected 2. I am almost certain it is happening in my views.

Here is the page that shows a user's courses:

<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
  <div class="row">
    {% if courses_list %}
    {% for course in courses_list %}
    <a type="button" class="btn btn-outline-secondary" href="{% url 'study:course-session'%}" >{{ course.subject }} {{ course.number}}-{{course.name}} </a>
    <br><br><br>
    {% endfor %}
    {% else %}
    <p class="text-center">You have not added any courses yet!</p>
    {% endif %}

  </div>
</div>

And here is the page that I am trying to filter the list of study sessions (which have a field course that is a ForeignKey to the Courses model):

     <h1><center>Upcoming Study Sessions</center></h1>

<div>
    <a class="btn btn-success" style="position:absolute; margin-right:2px; top:15%; right:0;" href="{% url 'study:courses' %}" role="button" >Back to My Courses</a>
  
  
</div>
<br><br>

<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
    <div class="row">
      <button type="button" class="btn btn-outline-secondary" >Date/Time: {{ session.date }} <br> Location: {{ session.location }} </button>
      <br><br><br>
  
    </div>
</div>

View for the template:

def CourseSessionView(request, course_pk):

course_wanted = Course.objects.get(id=course_pk)
try:
    return Study.objects.filter(course=course_wanted)
except:
    return messages.error(request, 'There are no upcoming study sessions at this time for the requested course.')

Model for course and session:

class Course(models.Model):
    SUBJECT_CHOICES = [
        ('AAS', 'AAS')
    ]
    subject = models.CharField(
        max_length=4, choices=SUBJECT_CHOICES, default='')
    number = models.PositiveSmallIntegerField(
        validators=[MaxValueValidator(9999)], default=0)
    name = models.CharField(max_length=100, default='')
    roster = models.ManyToManyField(
        Student, blank=True, related_name="courses")
    # Use [Student object].courses.all() to see all of a student's courses

    def __str__(self):
        return f"{self.subject} {self.number} - {self.name}"


class Study(models.Model):
    organizer = models.ForeignKey(Student, on_delete=models.CASCADE)
    date = models.DateTimeField()
    # Use [Student object].studies.all() to see all of a student's study sessions
    attendees = models.ManyToManyField(Student, related_name="studies")
    location = models.CharField(max_length=30)
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.date} - {self.location}"

Url:

path('<int:course_pk>/sessions/',
         views.CourseSessionView, name='course-session')

This is going to be a very general type of answer since you are not providing your models or your views, but I think the idea would be the following.

First, in your template you can pass a parameter for the course number in the url:

your_template.html

<a class="btn btn-outline-secondary" 
   href="{% url 'study:course-session' course.pk %}">
   {{ course.subject }} {{ course.number}}-{{course.name}}
</a>

Then in your view you can access that value, and from it get the course:

views.py

def the_view_name(request, course_pk):
    # Here you now have access to the course's primary key, pk, so you can get the 
    # course and filter the study sessions by that course, etc...

You will need to modify the urls.py so the view can accept this new parameter:

urls.py

path('the_view_name/<int:course_pk>', views.the_view_name, name='the_view_name'),

EDIT
Make the following changes:
First to your views.py:

def CourseSessionView(request, course_pk):

    try:
        course_wanted = Course.objects.get(id=course_pk)
    except:
        return messages.error(request, 'course not found')

    study_sessions = Study.objects.filter(course=course_wanted)

    if study_sessions.count() < 1:
        return messages.error(request, 'There are no upcoming study sessions at this time for the requested course')

    context = {
        'study_sessions': study_sessions,
    }

    return render(request, 'study/your_template_file.html', context)

Then in your html

<h1><center>Upcoming Study Sessions</center></h1>

<div>
<a class="btn btn-success" style="position:absolute; margin-right:2px; top:15%; right:0;" href="{% url 'study:courses' %}" role="button" >Back to My Courses</a>

</div>
<br><br>

<div class="container h-100" style="top:50%; bottom:50%; width:100%;">

  {% for session in study_sessions %}
  <div class="row">
   <button type="button" class="btn btn-outline-secondary" >Date/Time: {{ session.date }} <br> Location: {{ session.location }} </button>
   <br><br><br>
  </div>
  {% endfor %}
  
</div>

Note: The function based views' name doesn't require to be in PascalCase as in your case, it should be in snake_case .

The page that show the user's courses, there you need to pk of courses:


<div class="container h-100" style="top:50%; bottom:50%; width:100%;">
  <div class="row">
    {% if courses_list %}
    {% for course in courses_list %}
    <a type="button" class="btn btn-outline-secondary" href="{% url 'study:course-session' course.pk %}" >{{ course.subject }} {{ course.number}}-{{course.name}} </a>
    <br><br><br>
    {% endfor %}
    {% else %}
    <p class="text-center">You have not added any courses yet!</p>
    {% endif %}

  </div>
</div>

Your view for the template, i am defining it in snake_case , since its recommended way.

def course_session(request, course_pk):
    course_wanted = Course.objects.get(id=course_pk)
    study_courses=''
    try:
        study_courses= Study.objects.filter(course=course_wanted)
    except:
        messages.error(request, 'There are no upcoming study sessions at this time for the requested course.')
    else:
        return render(request,'anyfolder/anyfile.html',{'study_courses':study_courses})
    
    return render(request,'anyfolder/anyfile.html') #then it will show only your error message.

Your url in urls.py be like:

path('any_route_name/<int:course_pk>/', views.course_session, name='course_session')

Note: Never forget to pass / at the end of your url or route_name .

Then, in your any template file you can access it and run loop:

{% for study in study_courses %}
{{study.organizer}},{{study.date}}
{% endfor %}

Then, you can access all its properties, and take benefit of ManyToOne relation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM