A community feature application made by django framework.
- Made a virtual environment with virtualenv.
- Used dynamic URL connection between templates with inheritance.
- Did data migration with models and python class.
- Create CRUD feature by using modelForm, request and redirect.
- Added search bar to find room and description with django db model Q.
- Used cookie-based sessions to authenticate user information.
- Imported decorator module to restrict user authority.
- Made user registration form by using UserCreationForm
- pytjon: 3.9.12
- pip: 22.2.2
- Django: 4.1
Install: pip install virtualenv
Create: virtualenv env
Activte: source env/bin/activate
Deactivate: deactivate
Install: pip install django
Start project: django-admin startproject <project_name>
Run server: python3 manage.py runserver (on the project folder)
And you can see initial page on the browser with http://127.0.0.1:8000
Add base.apps.BaseConfig on the INSTALLED_APPS list of settings.py. And now, django can know this base app is installed.
urls.py
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
def home(request):
return HttpResponse('Home page')
urlpatterns = [
path('admin/', admin.site.urls),
path('', home),
]
Import HttpResponse from django.http and make a home function with simple HttpResponse return.
There are huge of urls and methods on this project, so we need to seperate main url and url based on the app.
By using include module, import base.url on the urlpatterns.
root.url.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('base.urls'))
]
Add templates destination on settings.py.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR / 'templates'
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Create return value with render module.
def home(request):
return render(request, 'home.html')
def room(request):
return render(request, 'room.html')
We can handle templates inside of html by using main.html and block content.
main.html
<body>
{% include 'navbar.html' %} {% block content %} {% endblock %}
</body>
Now, you can wrap other templates by usint {% extends 'main.html' %}.
home.html
{% extends 'main.html' %} {% block content%}
<h1>Home Template</h1>
{% endblock content %}
We can make values on view.py and send data by using context.
rooms = [
{'id':1, 'name':'Lets learn python!'},
{'id':2, 'name':'Design with me'},
{'id':3, 'name':'Frontend developers'},
]
def home(request):
context = {'rooms': rooms}
return render(request, 'home.html', context)
If you want to iterate with for loop, you can do like below.
<div>
<div>
{% for room in rooms %}
<div>
<h5>{{room.id}} -- {{room.name}}</h5>
</div>
{% endfor %}
</div>
</div>
Definitely, you are thinking about how can I use dynamic URL in django project. For doing this, fix urlpatterns of url.py and modify room function inside of view.py
def room(request, pk):
room = None
for i in rooms:
if i['id'] == int(pk):
room = i
context = {'room': room}
return render(request, 'base/room.html', context)
By doing this, we can check whether room's id is equal to pk value on the requested url. If it is correct, django will reponse specific template on the browser.
First data table for this project should be made inside of base/models.py.
# Class for data table - attributes are column field
class Room(models.Model):
# host =
# topic =
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
# participants =
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
After this, use makemigrations command and do migrate data.
python3 manage.py makemigrations
0001_initial.py is created on migrations folder.
python3 manage.py migrate
In order to check database, you need to make admin user.
python3 manage.py createsuperuser
After enter user information, we can use django administration page. But migrated room data is not seen now. Something should be added on admin.py.
from .models import Room
admin.site.register(Room)
Now you can see Rooms section on the admin page.
After we create and migrate Rooms data, it can be used as an objects and many kinds of methods like below. (all(), get(), filter())
views.py
def home(request):
rooms = Room.objects.all()
context = {'rooms': rooms}
return render(request, 'base/home.html', context)
def room(request, pk):
room = Room.objects.get(id=pk)
context = {'room': room}
return render(request, 'base/room.html', context)
- ModelForm: ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.
forms.py
from django.forms import ModelForm
from .models import Room
class RoomForm(ModelForm):
class Meta:
model = Room
fields = '__all__'
To create a new room and save, we can use RoomForm(request.POST).
view.py
# If create-room request POST
if request.method == 'POST':
form = RoomForm(request.POST)
# form validation
if form.is_valid():
form.save()
# redirect to the homepage
return redirect('home')
We can make updateRoom function to edit room information. If user click Edit link on the home.html, url.py will connect to update-room/<str:pk>/ and request updateRoom function. After edit this room's information, redirected into home page like below.
def updateRoom(request, pk):
room = Room.objects.get(id=pk)
form = RoomForm(instance=room)
if request.method == 'POST':
form = RoomForm(request.POST, instance=room)
if form.is_valid():
form.save()
return redirect('home')
context = {'form': form}
return render(request, 'base/room_form.html', context)
Such as updateRoom feature, you can add deleteRoom function on views.py.
def deleteRoom(request, pk):
room = Room.objects.get(id=pk)
if request.method == 'POST':
room.delete()
return redirect('home')
return render(request, 'base/delete.html', {'obj':room})
Django uses session to authenticate user on the browser. To understand this, we need to figure out what session is, what is differencies between session and cookies on web browser.
Cookies are client-side files that are stored on a local computer and contain user information. Sessions are server-side files that store user information. Cookies expire after the user specified lifetime. The session ends when the user closes the browser or logs out of the program.
Sessions are more secure than cookies, since they're normally protected by some kind of server-side security.
Django uses a cookie containing a special session id to identify each browser and its associated session with the site.
To authenticate user with session in django framework, you should import several modules and create loginPage, logoutUser function on views.py.
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
...
def loginPage(request):
if request.method == 'POST': # if user input any information
username = request.POST.get('username')
password = request.POST.get('password')
# Check user is exist
try:
user = User.objects.get(username=username)
except:
messages.error(request, 'User does not exist')
user = authenticate(request, username=username, password=password)
# if user is not None, login executed
if user is not None:
login(request, user)
return redirect('home')
else:
messages.errir(request, 'Username OR password does not exist')
context = {}
return render(request, 'base/login_register.html', context)
def logoutUser(request):
logout(request)
return redirect('home')
After add user authentication, you are going to restrict user authority to edit or update some information. There bunch of ways to do this, but I will use decorators and HttpResponse in django.
For doing this, you need to import modules on views.py.
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
And add annotaion to each function that need user login required like below.
@login_required(login_url='/login')
def createRoom(request):
...
We can check current user is equal to host of the room by using conditional statement.
if request.user != room.host:
return HttpResponse('You are not allowed here!!')
For now, we will make user resgistration functionality. There is a pre-made register form that django has. For this project, we will use UserCreationForm.
from django.contrib.auth.forms import UserCreationForm
And make registerPage function.
def registerPage(request):
form = UserCreationForm()
if request.method == 'POST':
form = UserCreationForm(request.POST)
# Change username into lower case
if form.is_valid():
user = form.save(commit=False)
user.username = user.username.lower()
user.save()
login(request, user)
return redirect('home')
else:
messages.error(request, 'An error occurred during registration')
return render(request, 'base/login_register.html', {'form': form})
After added {{form.as_p}}, we can see django user registration form.
<form method="POST" action="">
{% csrf_token %} {{form.as_p}}
<input type="submit" value="Register" />
</form>
- https://youtu.be/PtQiiknWUcI
- https://docs.djangoproject.com/en/4.0/topics/forms/modelforms/
- https://www.tutorialspoint.com/What-is-the-difference-between-session-and-cookies#:~:text=Cookies%20are%20client%2Dside%20files,files%20that%20store%20user%20information.&text=Cookies%20expire%20after%20the%20user,logs%20out%20of%20the%20program.