Doug Conran
Doug Conran

Reputation: 473

How do I pass data from 2 datasets to a Django view?

I have a simple Django project that consists of 3 datasets: Members --< mem_ev >-- Events such that any Member can go to any number of events and any event can have many members (ie a classic many to many relationship). I have the members, events, members per event and events per member templates working but I want to pass a count of the number of events per member in the main members list (list.html).

Given the following file structures how do I capture event_count per Member and how to I pass that to the relavant template (list.html)?

My app:urls.py file is:

app_name = 'wf'

urlpatterns = [ path('',views.members_list,name='member-list'),
                path('home/',views.members_list,name='member-list'),
                path('events/',views.events_list,name='event-list'),
                path('about/',views.about,name='wf-about'),
                path('event_detail/<int:id>/',views.event_detail,name='event_detail'),
                path('list_event_members/<int:id>/', views.list_event_members, name='list_event_members'),
                path('list_member_events/<int:id>/', views.list_member_events, name='list_member_events'),
                ]

My views.py file is:

def members_list(request):
    members = Member.objects.all()
    event_count = ?? What goes here ??      <------
    return render(request,'wf/list.html',{'members':members,'event_count':event_count})

def events_list(request):
    events = Event.objects.all()
    return render(request,'wf/events.html',{'events':events})

def event_detail(request,id):
    event = Event.objects.get(id=id)
    return render(request,'wf/event_detail.html',{'event':event})

def about(request):
    return render(request,'wf/about.html')

def list_event_members(request,id):
    event_members = Member.objects.filter(mem_ev__event_id=id)
    return render(request,'wf/list_event_members.html',{'event_members':event_members})

def list_member_events(request,id):
    member_events = Event.objects.filter(mem_ev__member_id=id)
    return render(request,'wf/list_member_events.html',{'member_events':member_events})

and the relvant template file (list.html) is:

{% extends "wf/base.html" %}
{% block content %}
  <h2>Members</h2>
    <table width="100%" cellpadding=8 style="border:1px solid black;">
      <thead class="table-success">
        <tr style="border:1px solid black;">
          <th scope="col"><h4>Member</h4></th>
          <th scope="col"><h4>Email</h4></th>
          <th scope="col"><h4>Events Attending</h4></th>
        </tr>
      </thead>
      <tbody>
      {% for member in members %}
        <tr {% if forloop.counter|divisibleby:2 %} style="background-color:gainsboro;"{% endif %}>
          <td><a  class="fw-bolder" href="{%  url 'wf:list_member_events' member.id %}">{{ member.lname }}, {{ member.fname }}</a></td>
          <td>{{ ?? What goes here ?? }}</td>    <-------------
          <td></td>
       </tr>
      {% endfor %}
      </tbody>
    </table>
{% endblock %}

Models.py file (as requested):

from django.db import models
from django.utils.text import slugify

class Event(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50,default="", null=False)
    description = models.TextField()
    cost = models.DecimalField(max_digits = 5, decimal_places = 2, default = 0.0)
    event_date = models.DateTimeField(null=True,blank=True)

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Event, self).save(*args, **kwargs)

    class Meta:
        ordering = ['event_date']

    def __str__(self):
        return self.title

class Member(models.Model):
    fname = models.CharField(max_length=50)
    lname = models.CharField(max_length=50)
    email = models.CharField(max_length=150, null=True, blank=True, default='[email protected]')
    tel = models.CharField(max_length=15, null = True, blank = True)

    class Meta:
        ordering = ['lname']

    def __str__(self):
        return self.lname

class mem_ev(models.Model):
    member_id = models.ForeignKey("Member",on_delete=models.CASCADE)
    event_id = models.ForeignKey("Event",on_delete=models.CASCADE)
    amt_paid = models.DecimalField(max_digits = 5, decimal_places = 2, default = 0.0)
    date_paid = models.DateTimeField(null=True,blank=True)

Upvotes: 0

Views: 46

Answers (1)

Doug Conran
Doug Conran

Reputation: 473

I've discovered what to do.

  1. Add an event_count field to the Member Model in Models.py (not forgetting to do makemigrations/migrate!)

  2. Step through each members = Member.objects.all() in views.py modifying the Member.event_count field with the updated count.

Here is my amended code for members_list in views.py

def members_list(request):
    members = Member.objects.all()
    for member in members:
        member.event_count = mem_ev.objects.filter(member_id=member.id).count()
    return render(request,'wf/list.html',{'members':members})

Upvotes: 0

Related Questions