Building a Social Media App With Python 3 & Django Beginners Tutorial 19: Tags (Part 2 of 2)

LegionScript
4 min readAug 7, 2021

--

Video Tutorial

Code on Github

In this tutorial we will continue the social media app by finishing our basic tag system that we started last time. We will build a explore page where posts can be filtered by tags. We will link the tag link to the filtered page where users can look at other posts with the same tag. We will also add a search bar on this to page to allow the user to filter by other tags. Let’s get started with this.

Explore Page View

First let’s create a simple view to handle showing the explore page. What we will want to do is see if there is a query in the url, if there is we will filter the posts by that tag, if there is not we will just show all of the posts. The url parameter will look like this /social/explore?query=abc. In this example, ‘abc’ is the tag we are filtering by. So we will find if there is something after query= and filter by that. Django has some built in functionality for this. We can use this:

self.request.GET.get('query')

This will look for ?query= and return anything after that. From there we can look for a tag with that name and filter the posts by that.

class Explore(View):  def get(self, request, *args, **kwargs):    query = self.request.GET.get('query')    tag = Tag.objects.filter(name=query).first()    if tag:      # filter posts by tag      posts = Post.objects.filter(tags__in=[tag])    else:      # show all posts      posts = Post.objects.all()    context = {      'tag': tag,      'posts': posts,      'explore_form': explore_form,    }    return render(request, 'social/explore.html', context)

Explore Page URL

Now that we have a basic view set up, let’s create a url pattern for this view.

path('explore/', Explore.as_view(), name='explore'),

This is just a basic url pattern similar to the others we’ve already created

Update Javascript URL

Now let’s update the link that is being put on the tag in the Javascript to go to this new url pattern we created.

let replacedText = bodyText.replace(/\s\#(.*?)(\s|$)/g, ` <a href="/social/explore?query=${words[j].substring(1)}">${words[j]}</a>`);

In our formatTags function, we replace the text with an anchor tag. Let’s update the href on the anchor tag to go to our explore page with the query parameter added to the end. We will use substring() to grab all of the characters except for the first one, which is the # and we don’t need that in our url.

Explore Search Form

Now we should be able to click on a link and it will take us to the url but it won’t work yet because we haven’t created a template yet. But before we do that, we will add a new form to our view. We want to create a search form to filter the explore page by other tags, allowing the user to search for posts with specific tags. To do this we need to build the form in our forms.py file first.

class ExploreForm(forms.Form):  query = forms.CharField(  label='',  widget=forms.TextInput(attrs={    'placeholder': 'Explore tags'    })  )

This will look very similar to other forms we’ve created. It just has one field and we add a placeholder attribute to the text input.

Update the View With the Form

Now let’s update our get method to include this form, let’s also add a post method to handle form submissions on this form.

class Explore(View):  def get(self, request, *args, **kwargs):    explore_form = ExploreForm()    query = self.request.GET.get('query')    tag = Tag.objects.filter(name=query).first()    if tag:      # filter posts by tag      posts = Post.objects.filter(tags__in=[tag])    else:      # show all posts      posts = Post.objects.all()     context = {      'tag': tag,      'posts': posts,      'explore_form': explore_form,    }    return render(request, 'social/explore.html', context)  def post(self, request, *args, **kwargs):    explore_form = ExploreForm(request.POST)    if explore_form.is_valid():      query = explore_form.cleaned_data['query']      tag = Tag.objects.filter(name=query).first()      posts = None      if tag:        # filter posts by tag        posts = Post.objects.filter(tags__in=[tag])      if posts:        context = {          'tag': tag,          'posts': posts        }      else:        context = {          'tag': tag        }      return HttpResponseRedirect(f'/social/explore?query={query}')    return HttpResponseRedirect('/social/explore/')

This should look pretty similar to the other views we’ve created with forms. But one difference here is what we are returning at the end of the post method. Instead of rendering a template or using redirect() we are using HttpResponseRedirect. Using this will allow us to pass in a url string which we can add the query at the end of it. We can’t do this with redirect() so using this function will just make it easier to pass in the parameters.

Explore Form Template

Finally we will create a template to show this explore page we will need to add the form to the top and then we will list out all of the posts that are in the posts variable in the context. That part will look very similar to what we do on post_list. Everything else should be handled by changing the query in the url. I’m not going to copy that entire file since it is pretty large but it is available in the github repository.

That concludes this tutorial where we finished up a basic tagging system. This could be extending to handle grabbing users using the @ character similar to how we found tags using the # character. For now we will stop here, there will be more videos in the future extending this application.

--

--