Adventures in Machine Learning

Building a Social Network with Django: Creating a Dweet System

Building a Social Network with Django: Adding Functionality for Creating and Displaying Dweets

Are you looking to build a social network platform using Django? In this article, we will explore how to add functionality to create and display dweets, as well as allowing users to follow and unfollow profiles.

Additionally, we will discuss how to submit dweets using Django forms. Dweets are essentially short messages or posts that are shared on the social network.

To create and display dweets, we need to work on both the back end and front end of the application. We will start by creating a new model to store dweets.

Creating a Dweets Model

Firstly, we need to create a new model for dweets in our Django application. In the models.py file, we define a new Dweets model as follows:

from django.db import models
from django.conf import settings

class Dweets(models.Model):
    text = models.CharField(max_length=240)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    class Meta:
        ordering = ['-created_at']

The text field is where the text content of the dweet will be stored.

The user field is defined as a foreign key to the Django User model and will be used to associate the dweet with a specific user. The created_at field will store the date and time when the dweet was created.

We also added the ordering option to our Dweets model’s Meta class to ensure that the dweets are displayed in reverse chronological order, with the most recent dweets displayed first. This is a common way to display social network posts.

Once we have created the Dweets model, we need to create a view for displaying the dweets.

Displaying Dweets

To display the dweets, we will create a new view in our views.py file and add the corresponding URL pattern to our urls.py file. The view will query the dweets from the database and render them using a template.

To do this, we will use the Dweets.objects.all() method in our view to retrieve all dweets from the database. We will then pass the dweets to our template using Django’s built-in context system.

In our template, we will use a for loop to iterate through the dweets and display them on the page. Here’s an example of what our view and template could look like:

# views.py
from django.shortcuts import render
from .models import Dweets

def dweets(request):
    dweets = Dweets.objects.all()
    return render(request, 'dweets.html', {'dweets': dweets})

# dweets.html
{% extends 'base.html' %}
{% block content %}
  

Dweets

{% for dweet in dweets %}

{{ dweet.text }}

{{ dweet.created_at }}
{% endfor %} {% endblock %}

We have created a new view called dweets that retrieves all dweets from the database and passes them to a template called dweets.html.

Our template then uses a for loop to display the text and creation date of each dweet on the page.

Submitting Dweets Using Django Forms

Next, we will add functionality for submitting dweets using Django forms. We will create a Django form that allows users to submit dweets from a text input field.

Creating a Dweet Form

To create our dweet form, we will use Django’s built-in ModelForm class, which makes it easy to create forms that correspond to our Django models. In our forms.py file, we will create a new DweetForm class that inherits from Django’s ModelForm class.

We will define a text field that corresponds to the text field in our Dweets model.

# forms.py

from django import forms
from .models import Dweets

class DweetForm(forms.ModelForm):
    text = forms.CharField(
        widget=forms.TextInput(attrs={'placeholder': 'Compose new dweet...'}),
        max_length=240,
        label='',
    )
    class Meta:
        model = Dweets
        fields = ['text']

Our DweetForm class defines a text field that uses a TextInput widget to render a text input field. We have also set a max_length of 240 characters, as defined in our Dweets model.

We have also added a placeholder attribute to provide a hint to the user on what to do.

We then define our DweetForm class’s Meta class, where we set the model to our Dweets model and define the fields to display in our form.

In this case, we only want to display the text field.

Displaying the Dweet Form

Now that we have created our DweetForm, we need to display it on the page and handle form submissions. In our views.py file, we will create a new view called new_dweet that displays our dweet form and handles form submissions using an HTTP POST request.

# views.py
from django.shortcuts import render, redirect
from .forms import DweetForm

def new_dweet(request):
    if request.method == 'POST':
        form = DweetForm(request.POST)
        if form.is_valid():
            dweet = form.save(commit=False)
            dweet.user = request.user
            dweet.save()
            return redirect('dweets')
    else:
        form = DweetForm()
    return render(request, 'new_dweet.html', {'form': form})

In our new_dweet view, we first check if the request method is POST. If it is, we create a form instance with the data submitted by the user.

We then check if the form is valid using the is_valid() method. If the form is valid, we save the dweet to the database but first set the user field to the current user to associate the dweet with the user.

We then redirect the user to the dweets page to see their new dweet. If the request method is not POST, we create a new instance of our DweetForm and render the new_dweet.html template, passing the form instance to the template in the context dictionary.

In our new_dweet.html template, we will render our form using the {{ form }} template tag, which will render the HTML for our form. We will also add a submit button to the form for submitting new dweets.

# new_dweet.html
{% extends 'base.html' %}
{% block content %}
  
{% csrf_token %} {{ form.as_p }}
{% endblock %}

Allowing Users to Follow and Unfollow Profiles

Lastly, let’s explore how to allow users to follow and unfollow profiles on our social network platform. We will use an HTTP POST request to handle the follow and unfollow actions.

Firstly, we will create a new model to store user follow relationships. In our models.py file, we will define a new Follows model as follows:

from django.db import models
from django.conf import settings

class Follows(models.Model):
    follower = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='following')
    following = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='followers')
    created_at = models.DateTimeField(auto_now_add=True)
    class Meta:
        unique_together = ('follower', 'following')

Our Follows model defines a follower field and a following field, both of which are foreign keys to the Django User model.

We have also added a created_at field to store the date and time when the follow relationship was created. We have also added the unique_together option to our Follows model’s Meta class so that there can be no duplicate follow relationships between a user and another user.

Creating a Follow and Unfollow View

Now that we have our Follows model, we need to create views to handle the follow and unfollow actions. In our views.py file, we will create two new views: follow and unfollow.

Both views will handle HTTP POST requests to create or delete Follows model instances.

# views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.http import Http404
from .models import User, Follows

@login_required
def follow(request):
    if request.method == 'POST':
        user_id = request.POST.get('user_id')
        user_to_follow = User.objects.filter(id=user_id).first()
        if user_to_follow:
            Follows.objects.update_or_create(follower=request.user, following=user_to_follow)
            messages.success(request, f"You have followed {user_to_follow.username}")
            return redirect('profile', user_to_follow.username)
        else:
            raise Http404

@login_required
def unfollow(request):
    if request.method == 'POST':
        user_id = request.POST.get('user_id')
        user_to_follow = User.objects.filter(id=user_id).first()
        if user_to_follow:
            Follows.objects.filter(follower=request.user, following=user_to_follow).delete()
            messages.success(request, f"You have unfollowed {user_to_follow.username}")
            return redirect('profile', user_to_follow.username)
        else:
            raise Http404

Our follow view handles HTTP POST requests to create a new Follows model instance.

We first get the user_id from the POST data and retrieve the user to follow from the database using the User.objects.filter() method. We then use the update_or_create() method on our Follows model to create a new follow relationship between the current user and the user to follow.

We also add a success message to the user using Django’s built-in message framework and redirect the user to the profile page of the user being followed. Our unfollow view handles HTTP POST requests to delete a Follows model instance.

It follows a similar pattern as our follow view, with the exception of using the delete() method to delete a follow relationship instead of creating a new one.

Displaying Follow and Unfollow Buttons

Now that we have our follow and unfollow views, we need to display follow and unfollow buttons on user profiles. In our profile.html template, we can use a simple if statement to display the follow or unfollow button depending on whether the user has an existing follow relationship with the current user.

# profile.html
{% extends 'base.html' %}
{% block content %}
  

{{ user.username }}

{% if request.user != user %} {% if request.user in user.followers.all %}
{% csrf_token %}
{% else %}
{% csrf_token %}
{% endif %} {% endif %} {% endblock %}

We have added a simple if statement that checks whether the current user is following the profile user. If the user is following the profile user, we display an “Unfollow” button that submits an HTTP POST request to our unfollow view.

If the user is not following the profile user, we display a “Follow” button that submits an HTTP POST request to our follow view.

Conclusion

In this article, we explored how to add functionality for creating and displaying dweets, allowing users to follow and unfollow profiles, and submitting dweets using Django forms. We hope this article has helped you on your journey to building your own social network platform using Django.

If you have any questions or comments, please leave them below.

Creating a Text Input Form: Making Form Submissions Possible

In our previous article, we explored how to create a text input form in Django using forms.py and render it in the dashboard template using HTML and Bulma.

In this article, we will discuss how to make form submissions possible and handle them in Django views.py.

Adding a Submit Button and Setting the HTTP Method

The next step in adding functionality to our text input form is to add a submit button and set the HTTP method to POST. In HTML, a form is submitted to a server using either a GET or POST request method.

A GET method is used to request information from a specified resource while a POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server. In our text input form, we will use the POST method to submit the form data to the server.

We will add a button to the form that the user can click to submit the form.


{% csrf_token %} {{ form.as_p }}

Handling Form Submissions in views.py

Once the form is submitted, we need to handle the form data in our views.py.

When the user submits the form, our Django view will receive a POST request. We will use Django’s Form API to handle the form submission and create a database entry for the user’s dweet.

# views.py
from django.shortcuts import render, redirect
from .forms import DweetForm
from .models import Dweet

def dashboard(request):
    form = DweetForm(request.POST or None)
    if form.is_valid():
        dweet = form.save(commit=False)
        dweet.user = request.user
        dweet.save()
        return redirect('dashboard')
    dweets = Dweet.objects.all()
    return render(request, 'dashboard.html', {'dweets': dweets, 'form': form})

In our dashboard view, we create an instance of our DweetForm and check if the form is valid. If the form is valid, we will create a new instance of our Dweet model and associate it with the current user.

We then save the model instance to the database. Finally, we redirect the user to the dashboard to see their new dweet.

We have also added a query_set variable to retrieve all dweets from the database and pass them to our template for display. The form variable will handle form validation and rendering of the form.

Improving the Display of DweetForm with Customizations

Lastly, we will explore how to customize the display of our DweetForm to improve its appearance. We can customize the visual appearance of our DweetForm using HTML and CSS.

# forms.py

from django import forms
from .models import Dweet

class DweetForm(forms.ModelForm):
    text = forms.CharField(
        widget=forms.TextInput(
            attrs={
                'class': 'textarea',
                'placeholder': 'What's on your mind?',
                'rows': 5,
                'cols': 60
            }
        ),
        max_length=240,
        label='',
    )
    class Meta:
        model = Dweet
        fields = ['text']

In our DweetForm class, we have customized the visual appearance of our form by adding a widget to our CharField. We have added the class attribute to our TextInput widget to reference a custom CSS style called textarea.

We have also set the placeholder, rows, and cols attributes to customize the look and size of our input field. To use the custom CSS style textarea, we have added the following code to our dashboard.html template.


{% block custom_css %}