filter objects dynamically on page render based on button click (beginner question)

245 views
Skip to first unread message

Phil Kauffman

unread,
Feb 12, 2020, 3:17:05 PM2/12/20
to Django users
Hello, I am struggling with trying to filter child objects based on parent object selection on index.html (sites.html in example). On my sites.html, I list the office sites and a button to click for each, upon clicking I want to load the profile list for users only at that site, presently it's loading all profiles for all sites, which I assume is because the profiles are loaded statically no matter which button is clicked on sites.html.

I'm thinking I need a JS onclick event?

models.py:
class Site(models.Model):

    name
= models.CharField(max_length=50)
    date
= models.DateField()
    manager
= models.CharField(max_length=50)
   
   
def save(self, *args, **kwargs):
       
super(Site, self).save(*args, **kwargs)
         
class Profile(models.Model):
   
Days = '1st'
   
Mids = '2nd'
   
Nights = '3rd'
   
Work_Schedule_Choices = [
     
(Days, 'Day Shift'),
     
(Mids, 'Mid Shift'),
     
(Nights, 'Night Shift'),
   
]  
    sitename
= models.ForeignKey(Site, on_delete=models.CASCADE)
    title
= models.CharField(max_length=100)
    schedule
= models.CharField(max_length=3,choices=Work_Schedule_Choices,default=Days)
    totalusers
= models.PositiveSmallIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(50)])



views.py:
def sites(request):
    sitelist
= Site.objects.all()
   
return render (request, 'App/sites.html', {'sitelist' : sitelist})

def sitedetail(request):
    site
= Site.objects.filter()
   
if request.method == 'GET':
       
return render(request, 'App/site-detail.html', {'site': site, 'profile_set': Profile.objects.all()})



sites.html (index)
{% extends 'App\base.html' %}
{% load crispy_forms_tags %}
{% block title %}Site Home{% endblock %}
{% block content %}
   
{% for Site in sitelist %}
<div <div  class="container">
   
<div  class="row justify-content-center">
       
<h5>{{ Site.name }}</h5>
       
<a href="{% url 'site-detail' %}" class="btn">View</a>
      </
div>
   
</div>
    {% empty %}
    <div class="noproject-wrapper center">
      <h3 class="grey-text">Sorry, you haven't created any sites yet.</
h3>
     
<a href="{% url 'site-create' %}" class="btn-large grey">
       
<i class="material-icons white-text left">Add Site</i>
        <span class="bold">Add Site</
span>
     
</a>
    </
div>
   
{% endfor %}
 
</div>
{% endblock %}


site-detail.html
{% extends 'App\base.html' %}
{% load crispy_forms_tags %}
{% block title %}Site Detail{% endblock %}
{% block content %}
<h1>This web form sucks</h1>
 <ul>
  {% for profile in profile_set  %}
  <li>{{ profile.title }}</
li>
 
{% endfor %}
 
</ul>
{% endblock %}






Bill Freeman

unread,
Feb 12, 2020, 6:46:42 PM2/12/20
to django-users
What happens in the browser stays in the browser, unless you do something about it.

Forgive me if I'm being too basic below:

There are three approaches to click and see a filtering change, with trade offs in performance, complexity, and the impact if the user's browser is on a humble box.
  1. When the user clicks, it's on a link, and you reload the page with the filter applied.  No JavaScript required.  Pretty slow.  more network load, more browser load, and more load on the server.  (I'm not going into the old approach of having an iframe and the link reloads the iframe because iframes are tricky, and if you're showing a big table, it's most of the page anyway.)  Do be sure that your images, CSS files, and JavaScript files are set to encourage the browser and/or the network to cache them, but the HTML will load every time, and the URL will likely show the filter settings (though you can do things with cookies and/or session store, but you will surprise your users someday.
  2. Load all the data in the first place, and use JavaScript in combination with CSS to hide the stuff that's filtered out.  If you go this way, do arrange to use CSS controlled by a class on a single containing element to control visibility, because doing big DOM modifications in JavaScript performs poorly.  This is the snappiest approach, but you have to have loaded everything, at cost of network and server load, even if you expect the user to filter later, and at the cost of RAM in the browser.  If the data's not that big, this is fine.  But if it's the catalog of a hardware chain or something else huge, you probably be doing it in pages.  Sometimes it's natural.  For example, I once did and event calendar for a school system.  I loaded a month at a time, and filtering within the month was peppy, but to go to a different month required a reload, and you couldn't show stuff from multiple months at one time.
  3. Use an AJAX request to replace part of the DOM with filtered data.  (The iframe hack is very much like this.)  If the data is most of your page, this isn't much more light weight than option 1, but the user doesn't see the page reload, which seems to count for style points.
There are JavaScript "frameworks" (e.g. VueJS) that will help you with 2 and especially 3, but you have to learn how to use the framework, and how to connect it to Django.  Those are useful things to learn, but they're not overnight reads, and can have performance pitfalls.

Good luck, Bill

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/b4bd97c3-1a36-436d-823a-b4f7003a29d0%40googlegroups.com.

Phil Kauffman

unread,
Feb 13, 2020, 7:36:37 AM2/13/20
to Django users
Bill,

Thank You for taking the time to respond. I will definitely need to read up on the options you presented. My first inclination was to get familiar with the first option as it seems easiest. However, now that you mention VueJS I will look into that as well.
To unsubscribe from this group and stop receiving emails from it, send an email to django...@googlegroups.com.

maninder singh Kumar

unread,
Feb 13, 2020, 7:59:15 AM2/13/20
to django...@googlegroups.com
Have you looked at permissions ?

Sent from my iPad
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/1c6cca2a-81bc-4df8-a714-344f6ad9081f%40googlegroups.com.

Bill Freeman

unread,
Feb 13, 2020, 9:51:42 AM2/13/20
to django-users
Note that Vue is one option among many and could either be overkill or not helpful enough for your specific use case OR BOTH.  It's just modern, and may be useful for projects beyond this one.

It doesn't hurt to be familiar with the grand daddy of them all: jQuery (though many sneer at it today).

To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/1c6cca2a-81bc-4df8-a714-344f6ad9081f%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages