Djitter - how to build a twitter clone using Django 2.0 - Part six

Djitter - how to build a twitter clone using Django 2.0 - Part six

Published 13. jun 2018 12:11 by Stein Ove Helset

We're now going to make it possible to post a djeet on our twitter clone. Yeah, I know a djeet sounds weird.

This part will be a little bit more exciting than the previous one. Now we are going to make it possible to add your own djeets! First we need to create a new file and open it in your editor.


$ touch djeet/forms.py

Write the following in forms.py.


# Import django forms and models

from django import forms
from django.utils.html import strip_tags

from .models import Djeet

class DjeetForm(forms.ModelForm):
  body = forms.CharField(required=True, widget=forms.widgets.Textarea(attrs={'placeholder': 'Djeet', 'class': 'form-control'}))
 
  class Meta:
    model = Djeet
    exclude = ('user',)

This form is similar to the two other forms we created earlier, but a little bit simpler. We only need the one field (body). In the Meta section we exclude 'user'. This is because it's a ForeignKey and it's required, if we try to save it before we add it the form will not validate. Open up the profile.html again to add the form render code. Under <h3>Add djeet</h3> title write the following code.


{% if form.errors %}
	{% for field in form %}
		{% for error in form.errors %}
			<div class="alert alert-danger">
				<b>{{ error|escape }}</b>
			</div>
		{% endfor %}
	{% endfor %}
	{% for error in form.non_field_errors %}
		<div class="alert alert-danger">
			<b>{{ error|escape }}</b>
		</div>
	{% endfor %}
{% endif %}

<form action="/{{ request.user.username }}/" method="post">
	{% csrf_token %}

	{% for field in form %}
		<div class="form-group">
			{{ field }}
		</div>
	{% endfor %}

	<input type="hidden" value="{{ request.path }}" name="redirect">
	<input type="submit" value="Post djeet" class="btn btn-primary">
</form>

This is quite simple. At the top we print errors if there are any and the bottom part of this code just prints the form. We add a hidden field called "redirect" where we fill in the current path so we know where to redirect the user after submit.

Getting the data from the form

Now there is only one more step. We need to get the data from this form too. So open up djeeterprofile/views.py and change it so it looks like this.


# Import django and models

from django.shortcuts import render, redirect
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.models import User
from djeeterprofile.forms import SignupForm, SigninForm
from djeet.forms import DjeetForm # Add this line

# Views

def profile(request, username): # Replace the old profile view with this one
  if request.user.is_authenticated:
    user = User.objects.get(username=username)
    
    if request.method == 'POST':
      form = DjeetForm(data=request.POST)

      if form.is_valid():
        djeet = form.save(commit=False)
        djeet.user = request.user
        djeet.save()
        
        redirecturl = request.POST.get('redirect', '/')

        return redirect(redirecturl)
    else:
      form = DjeetForm()

    return render(request, 'profile.html', {'form': form, 'user': user})
  else:
    return redirect('/')

def frontpage(request):
  if request.user.is_authenticated:
    return redirect('/' + request.user.username + '/') # Change this line
  else:
    if request.method == 'POST':
      if 'signupform' in request.POST:
        signupform = SignupForm(data=request.POST)
        signinform = SigninForm()
        
        if signupform.is_valid():
          username = signupform.cleaned_data['username']
          password = signupform.cleaned_data['password1']
          signupform.save()
          user = authenticate(username=username, password=password)
          login(request, user)
          return redirect('/')
      else:
        signinform = SigninForm(data=request.POST)
        signupform = SignupForm()
        
        if signupform.is_valid():
          login(request, signupform.get_user())
          return redirect('/')
    else:
      signupform = SignupForm()
      signinform = SigninForm()
  
    return render(request, 'frontpage.html', {'signupform': signupform, 'signinform': signinform})

We imported DjeetForm which we just created. The next code we added checks if the request method is of type POST. We then receives the data from the form and saves it. This code "form.save(commit=False)" makes it possible for us to validate the form, but not add it to the database. On the next line we add the user which is authenticated and then we are able to save without any errors and redirect the user back to his profile.

Testing the site

Now you can open the site in your browser again and sign in. A post a djeet form will be available at the right side of your screen, go a head and try it. Once you have posted the djeet it will become available in your feed to the left.

If you've got any questions your are more than welcome to leave a comment and I'll answer as soon as possible.

Next part

Share this post

Comments

Igor

10. aug 2018 15:37

I'm having "django.contrib.auth.models.User.DoesNotExist: User matching query does not exist." when I try to run this code. Is seems to come back to this equivalence: user = User.objects.get(username=username)

The functions of the profile page work, including adding posts, but it then completely breaks down in the feed part.

Could you explain those lines better, so I can get an idea how to fix it?

Stein Ove Helset

12. aug 2018 16:34

Hi Igor.
Would you mind sending me a zipped version of your code? Send it to steinove@ahackersday.com
It's a little bit hard for me to know what it can be without looking at the code.

martin

25. sep 2018 14:09

Hei! Found another little typo, here in the second paragraph of this page:

<h3>Add djeet</h2>

Meant to be: <h3>Add djeet</h3>

Hope this helps someone : )

Stein Ove Helset

26. sep 2018 05:41

Thanks again, Martin.
Replaced it with "h3"!

Add comment