Django Query Filter Menu

194 views Asked by At

I want to build a similar, but significantly simpler User list page with a query filter menu:

Player List from nhl.com

User can apply individual filters, or chain them. I prefer AJAX, but am happy to start off an 'apply filters' submit button.

Current look

class User(AbstractBaseUser):
id = models.AutoField(primary_key=True)
created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
modified = models.DateTimeField(auto_now=True, null=True, blank=True)

first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(verbose_name='email address', max_length=255, unique=True, )

date_of_birth = models.DateField('date of birth', null=True)
avatar = models.ImageField('profile picture', upload_to='static/images/avatars/', null=True, blank=True)
logline = models.CharField(max_length=100, blank=True)
driving = models.BooleanField(default=False)
license_class = models.IntegerField(blank=True, null=True, choices=LICENSE_CHOICES)
vehicle = models.CharField(max_length=100, blank=True)
show = models.ForeignKey(Show, on_delete=models.CASCADE, null=True, blank=True)
links = ArrayField(models.URLField(max_length=100, blank=True, null=True), blank=True, null=True)
focus = ArrayField(models.CharField(max_length=50, null=True, choices=FOCUS_CHOICES), blank=True, null=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
call_preference = ArrayField(models.CharField(max_length=90, choices=FOCUS_CHOICES, null=True), blank=True, null=True)
blocked = models.ManyToManyField('self', related_name='blocked', blank=True)
qualified_positions = ArrayField(models.CharField(max_length=50, choices=FOCUS_CHOICES, null=True), null=True, blank=True)
years = models.IntegerField(default=1)
trade = ArrayField(
    models.CharField(max_length=50, choices=TRADE_CHOICES),
    null = True,
    blank = True
)

member = models.BooleanField(default=False)

available = models.BooleanField(default=False)
available_from = models.DateField(null=True, blank=True)
available_to = models.DateField(null=True, blank=True)
range = DateRangeField(null=True, blank=True)

objects = UserManager()

Filters: - Available - BooleanField, if available on date specified - Position - CharField choices, can pick 1 - Trade - BooleanField choices, can pick multiple - Member - Is member of selected union

Currently have generic ListView, and UserManager() full of recently typed and untested queries that likely need much work.

    def base_get(self, start_date, **kwargs):
    #user = kwargs.pop('user')
    rightthefucktoday = datetime.date.today()
    rightthefucktomorrow = datetime.date.today() + datetime.timedelta(days=1)
    f = []
    if start_date and 'end_date' in kwargs:                                 ## is user.range contains the range of dates
        diff = kwargs.pop('end_date') - start_date
        date_range = []
        for i in range(diff.days + 1):
            date_range.append(start_date + datetime.timedelta(days=i))
        f = self.filter(range_range=(date_range)).order_by('years', 'member')#.exclude(user=user)
        return f
    elif start_date and not 'end_date' in kwargs:
        ## if end date isn't specified
        if start_date == rightthefucktomorrow:
            f = self.filter(available=True).order_by('years', 'member').exclude(available_to=rightthefucktoday)   ## if the date specified is tomorrow
            return f
        else:
            f = self.filter(range_contains = start_date).order_by('years', 'member')#.exclude(user=user) # if date specified is not tomorrow
            return f
    else:   ## no date specified, which is impssible
        f = self.filter(available=True).order_by('years', 'member')#.exclude(user=user) #return if available
        return f


def get_by_position(self, position):
    u = self.filter(qualified_positions_contains=position)
    return u

def get_by_trade(self, *args):
    shit = []
    for i in args:
        shit.append(i)
    c = self.filter(trade_contains=shit)
    return c

def get_by_union(self, union): ## input must be "IATSE 891", "IATSE 669", or "ACFC 2020"
    return self.filter(union__union__exact_=union)


def get_by_member(self):
    return self.filter(member=True) ##if only members


def master_query(self, start_date, *args, **kwargs): ## args must be trade details TODO: Test, and build test cases
    f, u, c, k = []
    if 'end_date' in kwargs: f = self.base_get(start_date, kwargs.pop('end_date'))
    else: f = self.base_get(start_date)
    it = f

    if 'position' in kwargs: u = self.get_by_position(kwargs.pop('position')); it = it | u
    if 'union' in kwargs: c = self.get_by_union(kwargs.pop('union')); it = it | c
    if args.count() != 0: k = self.get_by_trade(args); it = it | k
    if 'member' in kwargs: you = self.get_by_member(); it = it | you

    return it

If someone could nudge me in the right direction as far as handling the template and view properly - I'd love you forever

Thank you

1

There are 1 answers

0
Chuck On

One way to apply filters is by using GET parameters. (The parts after the '?' in URLs [e.g. https://search.yahoo.com/search?p=test+search]). So create a form in your template with method='GET' and handle the GET parameters via self.request.GET (I think you have to enable the RequestContextProcessor for this).