# **TRY DJANGO 1.11 | Start Project**

## **Django Overview**
Salah satu permasalahan yang saat ini sering kita jumpai ialah bagaimana cara membangun web dengan cepat dan efektif? Maka, Django menawarkan pengalaman yang dibutuhkan ini. Django sendiri menggunakan bahasa pemrograman Python yang ramah untuk pemula tapi juga dapat dikembangkan lebih bagi pengguna expert.
Beberapa aplikasi yang sering kita gunakan sangat mungkin bahwa dalam pengembangannya menggunakan django. Seperti instagram, pinterest, dropbox, dsb.
Cara kerja Django yang sebenarnya secara spesifik ialah, ketika kita mengunjungi sebuah domain, system akan menangani **url** yang diberikan baik itu url singkat maupun versi yang lebih panjang. Kemudian, akan **dikembalikan** berdasarkan informasi yang tersimpan pada server. Bahkan, django akan **mengingat** pengguna saat masuk ke dalam web tersebut, sebgaiamana pengguna terakhir yang mengakses. Sekalipun, saat berada pada jangka waktu yang lama tidak mengunjungi website tersebut. Dalam lingkup yang sama, django juga mengingat **preferensi** penggunanya, yang tersimpan pada back end system yang mereka miliki. Beberapa layanan yang dapat dimiliki dan dikelola oleh Django ialah seperti akun, video, content, analytics, menu listing, bahkan mungkin untuk memuat informasi promosi, dsb.
---
## **Django Framework**
 image source: https://www.biznetgio.com/news/django
- Model, data yang ingin ditampilkan atau penghubung antara interface pengguna dan database, biasanya dari database. Model biasanya memiliki kode models.py.
- View, berisi logika UI dan menjadi penanganan permintaan yang mengembalikan template dan konten yang relevan berdasarkan permintaan dari pengguna. Mencakup elemen HTML, CSS, dan front-end lainnya. View biasanya memiliki kode views.py.
- Template, sebuah file teks (layaknya file HTML) yang berisi letak halaman web. Template biasanya memiliki kode templates.
Semua aktivitas **back-end**, seperti logika dan query dikerjakan pada Model. Sementara, semua hal yang menyangkut tampilan **front-end** dikelola oleh Template. Dengan demikian, developer tidak perlu menggunakan dua **framework** terpisah untuk back-end dan front-end saat membangun website dan aplikasi dengan framework **Django**.
---
:::success
:bulb: **Attention**
When you finish read this section, you can accsess my next documentation, that's talk about about create database and logic UI in Django1.11, click this link:
[TRY DJANGO 1.11 (Database & Logic UI)](https://hackmd.io/@syafaa/TryDjango2)
Hope you enjoy it!!!
:::
---
## **Start Django Project**
### **1. Django Environtment**
Untuk menjalankan django. diperlukan beberapa software pendukung ialah:
1. Python (Phyton3) dan depedencynya
2. Pip
3. Virtualenv
4. Sublime Text
Berikut merupakan langkah untuk menyiapkan blank django project:
1. Melakukan update vm yang digunakan
```
sudo apt-get update
```
2. Melakukan instalasi sublime text
```
wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/sublimehq-archive.gpg > /dev/null
echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list
sudo apt-get update
sudo apt-get install sublime-text
```

3. Melakukan instalasi Phyton3 dan pip
```
sudo apt install python3 python3-pip
```

4. Memastikan python dan pip telah terinstal
```
python3 --version
pip3 --version
```

5. Melakukan instalasi development package
```
sudo apt libreadline-gplv2-dev libncursesw5-dev libpq-dev python3-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev
```

6. Membuat direktori baru Dev sekaligus trydjango1-11 di dalamnya
```
mkdir Dev && cd Dev
mkdir trydjango1-11 && cd trydjango1-11
```
7. Melakukan instalasi virtualenv python
```
sudo apt install python3-virtualenv
virtualenv -p python3 .
```


8. Menginstal django 1.11 di dalam virtualenv
```
source /bin/activate
pip install django==1.11.*
```

### **2. Start Django Project**
1. Membuat project django bernama muypicky pada direktori src
```
mkdir src && cd src
django-admin.py startproject muypicky .
```

2. Membuat file yang dibutuhkan dalam direktori setting
```
cd muypicky/
mkdir settings && cd settings
touch _init_.py
touch base.py
touch local.py
touch production.py
```
3. Mengisi file base.py dengan isi file settings.py
```
cp settings.py settings/base.py
```
mengubah BASE_DIR pada base.py menjadi
```
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
```

4. Mengisi file _init_.py sebagai berikut:
```
from .base import *
from .production import *
try:
from .local import *
except:
pass
```
5. Menginstal beberapa pustaka tambahan
```
pip install psycopg2
pip install gunicorn
pip install django-crispy-forms==1.7.2
pip install dj-database-url==0.5.0
pip install pillow
```
dan melihat version setiap instalasi yang dilakukan
```
pip freeze > requirements.txt
```

6. Menjalankan migration
```
python manage.py migrate
```

7. Membuat superuser
```
python manage.py createsuperuser
```

8. Menjalankan server
```
python manage.py runserver
```
dan mengakses web melalui http://127.0.0.1:8000/
![Djangoo [Running] - Oracle VM VirtualBox 25_03_2024 09_06_35](https://hackmd.io/_uploads/B1ICgwR0T.png)

9. Melengkapi file local.py dan production.py
```
cp base.py local.py
cp base.py production.py
```
dengan perubahan pada production.py sebagai berikut:
```
DEBUG = False
SECRET_KEY = "random letter or number"
```
### **3. Mengkonfigurasi Website**
1. Membuat menu listing
```
python manage.py startapp restaurants .
```
2. Mengatur tampilan page dalam file views.py
```
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
return HttpResponse("hello")
```
3. Mengatur url pada file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from restaurants.views import home
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', home),
]
```
## **HTML and Django**
### **1. Rendering HTML**
HTML merupakan bahasa yang dimengerti oleh browser, kemudian diterjemahkan hingga menjadi tampilan yang dilihat langsung oleh penggunanya.
- Python string
```
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
html_ = """<!DOCTYPE html>
<html lang=en>
<head>
<head/>
<body>
<h1>Hello world</h1>
<p>This is html coming trough</p>
</body>
</html>
"""
return HttpResponse(html_)
```

- Python string subtitution
```
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
html_var = 'trial'
html_ = f"""<!DOCTYPE html>
<html lang=en>
<head>
<head/>
<body>
<h1>Hello world</h1>
<p>This is trial coming trough</p>
</body>
</html>
"""
return HttpResponse(html_)
```

### **2. Render a Django Template**
#### **a. String html**
1. Membuat file base.html
```
touch /home/ubuntu//Dev/trydjango1-11/lib/python3.8/site-palates/base.html
```
2. Mengisi file base.html sebagaimana berikut:
```
<!DOCTYPE html>
<html lang=en>
<head>
<head/>
<body>
<h1>
Hello World!
</h1>
<p>
This is trial coming trough
</p>
</body>
</html>
```
3. Mengubah isi file base.py pada bagian TEMPLATES, sebagai berikut:
```
'DIRS': [os.path.join(BASE_DIR, 'templates')],
```
4. Mengisi file views.py, sebagaimaan berikut:
```
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
return render(request, "base.html", {})
```
5. Mengubah isi file _init_.py dalam direktori settings, sebagaimana berikut:
```
from .base import *
#from .production import *
#try:
# from .local import *
#except:
# pass
```
6. Akses pada url http://172.0.0.1:8000/

#### **b. Context variable**
1. Untuk menggunakan variable pada file html. Maka ubah file base.html sebagaimana berikut:
```
<!DOCTYPE html>
<html lang=en>
<head>
</head>
<body>
<h1>
Hello world
</h1>
<p>
This is {{ html_var }} coming trough
</p>
<p>
Your random number is {{ num }}!
</p>
</body>
</html>
```
2. Mengubah isi file views.py menjadi sebagaimana berikut:
```
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
num = random.randint(0, 100000000)
return render(request, "base.html", {"html_var": True, "num": num})
```
3. Akses pada url http://172.0.0.1:8000/

### 3. Context in Django Templates
Memahami bagaimana kerja sesungguhnya dari context di dalam template. Ketika pengguna mengubah apa yang dibutuhkan pada file views.py (manage url), maka tampilan pada web yang di render akan menyesuaikan kondisi yang dicantumkan pada file template base.html (html). Untuk menerapkannya, ikuti langkah berikut:
1. Mengisi file base.html dengan sebagaimana berikut:
```
<!DOCTYPE html>
<html lang=en>
<head>
</head>
<body>
<h1>
Hello World!
</h1>
<p>
This is <code>{% verbatim %}{{ html_var }}{% endverbatim %}</code> coming trough
</p>
<p>
{^ if bool_item %}
Your random number is {{ num }}!
{% endfor %}
</p>
<p>
{% for some_item in some_list %}
{{ some_item }}<br/>
{% endfor %}
</p>
<p>
Some item is {{ some_item }}
</p>
</body>
</html>
```
2. Mengubah isi file pada views.py, sebagaimana berikut:
```
import random
from django.http import HttpResponse
from django.shortcuts import render
def home(request):
num = None
some_list = [
random.randint(0, 100000000),
random.randint(0, 100000000),
random.randint(0, 100000000)
]
condition_bool_item = False
if condition_bool_item:
num = random.randint(0, 100000000)
context = {
"num": num,
"some_list": some_list
}
return render(request, "base.html", context)
```
3. Mengakses web pada url http://172.0.0.1:8000/

### **4. Template In Heritance**
Template in heritance meungkinkan pengguna untuk mengubah layout content di dalam web yang sebenarnya berada pada template yang berbeda-beda, sekaligus memanggil extends untuk template yang dimaksud. Disini saya menjalankan template in heritance sebagai berikut:
1. Membuat file base.html dan mengisinya sebagaimana berikut:
```
<!DOCTYPE html>
<html lang=en>
<head>
<title>{% block head_tittle %}EXO-l.com{% endblock head_tittle %}</title>
<head>
<body>
<h1>EXO-l.com</h1>
<a href="/">Home</a>
<a href="/about/">About</a>
<a href="/content/">Our Content</a>
<div class="container">
{% block content %}{% endblock content %}
</div>
</body>
</html>
```
2. Membuat file home.html dan mengisinya sebagaimana berikut:
```
{% extends "base.html" %}
{% block content %}
<h1>
Wellcome!
</h1>
<h3>
{{ block.super }}
</h3>
<p>
This is <code>{% verbatim %}{{ html_var }}{% endverbatim %}</code> coming trough
</p>
<p>
{% if num is not None %}
Random number is {{ num }}
{% endif %}
</p>
<p>
{% for some_item in some_list %}
{% if some_item|divisibleby:"2" %}
Even number
{% endif %}
{{ some_item }} <br/>
{% endfor %}
</p>
<p>
Some item is {{ some_item }}
</p>
{% endblock content %}
```
3. Membuat file about.html dan mengisinya sebagaimana berikut:
```
{% extends "base.html" %}
{% block head_tittle %}About || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<p>About</p>
{% endblock %}
```
4. Membuat file content.html dan mengisinya sebagaimana berikut:
```
{% extends "base.html" %}
{% block head_tittle %}Our Content || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<p>Our Content</p>
{% endblock %}
```
5. Mengubah file urls.py sebagaimana berikut:
```
from django.conf.urls import url
from django.contrib import admin
from restaurants.views import home, about, content
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', home),
url(r'^about/$', about),
url(r'^content/$', content),
]
```
6. Mengakses web pada url http://172.0.0.1:8000/



### **5. Template Tag**
1. Membuat file nav.html, css.html, js.html, dan sidebar.html di dalam direktori templates/snippets/
```
touch /home/ubuntu/Dev/trydjango1-11/lib/python3.8/site-packages/django/contrib/admin/templates/snippets/nav.html
touch /home/ubuntu/Dev/trydjango1-11/lib/python3.8/site-packages/django/contrib/admin/templates/snippets/css.html
touch /home/ubuntu/Dev/trydjango1-11/lib/python3.8/site-packages/django/contrib/admin/templates/snippets/js.html
touch /home/ubuntu/Dev/trydjango1-11/lib/python3.8/site-packages/django/contrib/admin/templates/snippets/sidebar.html
```
2. Mengubah file nav.html, sebagaimana berikut:
```
<div class='container'>
<h1>EXO-l.com</h1>
<a href="/">Home</a>
<a href="/about/">About</a>
<a href="/content/">Our Content</a>
</div>
```
3. Mengubah file css.html dengan Bootstrap CDN CSS , sebagaimana berikut:
```
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
```
4. Mengubah file js.html dengan Bootstrap CDN JavaScript, sebagaimana berikut:
```
<script src='https://code.jquery.com/jquery-3.7.1.min.js'></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
```
5. Mengubah file sidebar.html, sebagaimana berikut:
```
<ul>
<li>Suho</li>
<li>D.O.</li>
<li>Xiumin</li>
<li>Chen</li>
<li>Baekhyun</li>
<li>Chanyeol</li>
<li>lay</li>
<li>Kai</li>
<li>Sehun</li>
</ul>
```
6. Mengubah file base.html, sebagaimana berikut:
```
<!DOCTYPE html>
<html lang=en>
<head>
<title>{% block head_tittle %}EXO-l.com{% endblock head_tittle %}</title>
{% include 'snippets/css.html' %}
<head>
<body>
{% include 'snippets/nav.html' %}
<div class='container'>
{% block content %}{% endblock content %}
</div>
{% include 'snippets/js.html' %}
</body>
</html>
```
7. Mengubah file about.html menjadi sebagaimana berikut:
```
{% extends "base.html" %}
{% block head_tittle %}About || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<p>About</p>
{% include 'snippets/sidebar.html' %}
{% endblock %}
```
8. Mengubah file content.html menjadi sebagaimana berikut:
```
{% extends "base.html" %}
{% block head_tittle %}Our Content || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<p>Our Content</p>
{% include 'snippets/sidebar.html' %}
{% endblock %}
```
9. Mengakses web pada url http://172.0.0.1:8000/



### **6. Class Based View**
Class based view ialah pendekatan yang memungkinkan untuk mengorganisasi logika tampilan yang mengimplementasikan metode-metode khusus yang dipanggil berdasarkan jenis permintaan HTTP yang diterima (seperti GET, POST, PUT, DELETE, dll.).
Get methode
1. Mengubah file views.py, sebagaimana berikut:
```
import random
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
def home(request):
num = None
some_list = [
random.randint(0, 100000000),
random.randint(0, 100000000),
random.randint(0, 100000000)
]
condition_bool_item = False
if condition_bool_item:
num = random.randint(0, 100000000)
context = {
"num": num,
"some_list": some_list
}
return render(request, "home.html", context)
def about(request):
context = {
}
return render(request, "about.html", context)
def content(request):
context = {
}
return render(request, "content.html", context)
class ContentView(View):
def get(self, request, *args, **kwargs):
print(kwargs)
context = {
}
return render(request, "content.html", context)
```
2. Mengubah file urls.py sebagaimana berikut:
```
from django.conf.urls import url
from django.contrib import admin
from restaurants.views import home, about, content, ContentView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', home),
url(r'^about/$', about),
url(r'^content/(?P<id>\d+)/$', ContentView.as_view()),
]
```
3. Mengakses web pada url http://172.0.0.1:8000/

halaman baru bisa diakses setelah menambahkan angka pada url http://172.0.0.1:8000/365/, sebagaimana berikut:


### **7. Template View**
Template view ini merupakan penggabungan antara template yang digunakan dengan menyertakan template lain saat proses rendering. Berikut langkah yang saya lakukan ketika menggunakan template view:
1. Mengubah isi file views.py menjadi sebagimana berikut:
```
import random
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, *args, **kwargs):
context = super(HomeView, self).get_context_data(*args, **kwargs)
num = None
some_list = [
random.randint(0, 100000000),
random.randint(0, 100000000),
random.randint(0, 100000000)
]
condition_bool_item = False
if condition_bool_item:
num = random.randint(0, 100000000)
context = {
"num": num,
"some_list": some_list
}
return context
class AboutView(TemplateView):
template_name = 'about.html'
class ContentView(TemplateView):
template_name = 'content.html'
```
2. Mengubah isi file urls.py menjadi sebagimana berikut:
```
from django.conf.urls import url
from django.contrib import admin
from restaurants.views import HomeView, AboutView, ContentView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', HomeView.as_view()),
url(r'^about/$', AboutView.as_view()),
url(r'^content/$', ContentView.as_view()),
]
```
3. Mengakses web dengan url http://172.0.0.1:8000/



## **Remember Things**
### **1. Remembering things with Models**
Dengan menggunakan model, Django memungkinkan pengembang untuk menyimpan data dalam database secara terstruktur dan terorganisir menggunakan model-model yang didefinisikan.
1. Membuat superuser baru
```
python manage.py createsuperuser
```
2. Akses 127.0.0.1:8000/admin/ dan masuk ke superuser yang dibuat.


File yang ada pada halaman admin, users, auth , dsb tersimpan pada database di file db.sqlite3. Yang kemudian di import melalui settings/base.py. Untuk itu, ketika hendak melakukan perubahan pada halaman, harus dijalankan perintah migration.
3. Mengubah isi file models.py di dalam direktori restaurants, sebagaimana berikut:
```
from django.db import models
class RestaurantLocation(models.Model):
name = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
```
4. Mengubah isi file admin.py di dalam direktori restaurants sebagaimana berikut:
```
from django.contrib import admin
from .models import RestaurantLocation
admin.site.register(RestaurantLocation)
```
5. Mengubah isi file base.py, menambahkan direktori restaurant pada bagian INSTALLED_APP, sebagaimana berikut:
```
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'restaurants',
]
```
6. Mengirim perubahan dan melakukan migration
```
python manage.py makemigrations
python manage.py migrate
```
7. Check melalui browser

menambahkan object:


### **2. More on Models Field**
1. Membuat aplikasi tambahan yaitu Event
```
python manage.py startapp events
```
2. Mengisi file models.py di dalam direktori events, sebagaimana berikut:
```
from django.db import models
class Event(models.Model):
name = models.CharField(max_length=120)
artist = models.CharField(max_length=120, null=True, blank=True)
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
```
3. Mengisi file admin.py direktori events sebagaimana berikut:
```
from django.contrib import admin
from .models import Event
admin.site.register(Event)
```
4. Menambahkan direktori events ke dalam instalation app pada file base.py, sebagimana berikut:
```
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'restaurants',
'events',
]
```
5. Menjalankan migration
```
python manage.py makemigrations
python manage.py migrate
```

6. Mengakses melalui browser

menambahkan object:

7. Mengubah file models.py menjadi sebagaimana berikut:
```
from django.db import models
class Event(models.Model):
name = models.CharField(max_length=120)
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
```
8. Menjalankan migration
```
python manage.py makemigrations
python manage.py migrate
```

9. Akses melalui browser dan lakukan perubahan


---
### **3. Displaying Saved Data**
1. Membuat file events.html
```
touch events/templates/events/event_list.html
```
2. Mengubah isi file views.py
```
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView
from .models import Event
def events_listview(request):
template_name = 'events/events_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
```
2. Mengubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import events_listview
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', events_listview),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
4. Mengisi file event_list.html
```
{% extends "base.html" %}
{% block head_tittle %}Events || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Events List</h1>
<ul>
{% for obj in object_list %}
<li>{{ obj }} <br/>
{{ obj.name }} by {{ obj.artist }} as a {{ obj.category }} at {{ obj.location }} held on {{ obj.Event_date }}; added on: {{ obj.timestamp }}; editted on:{{ obj.update }}.</li>
{% endfor %}
</ul>
{% endblock %}
```
5. Mengubah file models.py
```
from django.db import models
class Event(models.Model):
name = models.CharField(max_length=120)
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
```
6. Akses melalui browser

### **4. Understanding QuerySets**
Queryset digunakan untuk berinteraksi dengan data dalam database. Dengan ini, pengguna dapat membuat, memfilter, dan memanipulasi queryset untuk mendapatkan data yang diinginkan dari database.
1. Menjalankan shell python
```
python manage.py shell
```
2. Melihat database
```
>>> from events.models import Event
>>> Event.objects.all()
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>]>
>>> for obj in Event.objects.all():
... print(obj.name)
...
BLOOM
SU:HOME
LONSDALEITE
```

3. Melihat database dengan filter
```
>>> qs = Event.objects.all()
>>> qs.filter(category__iexact='Fancon')
<QuerySet [<Event: BLOOM>]>
>>> qs.filter(category__iexact='Concert')
<QuerySet [<Event: SU:HOME>, <Event: LONSDALEITE>]>
```

4. Mengupdate database
```
>>> qs.update(category='Fancon')
3
>>> qs.filter(category__iexact='Concert')
<QuerySet []>
>>> qs.filter(category__iexact='Fancon')
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>]>
```

5. Menambahkan objek
```
>>> obj = Event()
>>> obj.name = "Saranghaeyo Indonesia"
>>> obj.artist = "Xiumin, Chen"
>>> obj.category = "Event"
>>> obj.location = "Jakarta Utara"
>>> obj.Event_date = "2024-05-04"
>>> obj.save()
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>]>
```

lihat melaui ListView:

6. Membuat queryset2 dengan filter
```
>>> qs = Event.objects.all()
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>]>
>>> qs2 = Event.objects.filter(category__iexact='Fancon')
>>> qs2
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>]>
>>> qs.exist()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'QuerySet' object has no attribute 'exist'
>>> qs.exists()
True
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>]>
```

7. membuat objek tambahan dalam satu line
```
>>> obj = Event.objects.create(name='The Eternity', artist= 'Chanyeol', category='Fancon', location='Jakarta', Event_date='2024-03-09') >>> qs = Event.objects.all()
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>, <Event: The Eternity>]>
```

8. Filter data dengan exclude
```
>>> qs = Event.objects.filter(category__iexact='Fancon').exclude(name__icontains='BLOOM') >>> qs
<QuerySet [<Event: SU:HOME>, <Event: LONSDALEITE>, <Event: The Eternity>]>
>>> qs = Event.objects.all()
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>, <Event: The Eternity>]>
>>> qs = Event.objects.filter(category__iexact='Fancon')
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: The Eternity>]>
```

### **5. Generic List View**
Dalam hal ini, ialah menampilkan daftar objek dari suatu model dalam bentuk daftar yang diambil dari database.
- Memfilter dengan menambahkan class baru
1. Mengubah isi file views.py
```
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView, ListView
from .models import Event
def events_listview(request):
template_name = 'events/events_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class EventListView(ListView):
queryset = Event.objects.all()
template_name = 'events/events_list.html'
class FanconEventListView(ListView):
queryset = Event.objects.filter(category__iexact='Fancon')
template_name = 'events/events_list.html'
class ConcertEventListView(ListView):
queryset = Event.objects.filter(category__iexact='Concert')
template_name = 'events/events_list.html'
class EventEventListView(ListView):
queryset = Event.objects.filter(category__iexact='Event')
template_name = 'events/events_list.html'
```
2. Mengubah isi file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
FanconEventListView,
ConcertEventListView,
EventEventListView,
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/fancon$', FanconEventListView.as_view()),
url(r'^events/concert$', ConcertEventListView.as_view()),
url(r'^events/event$', EventEventListView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
3. Cek melalui browser


- Memfilter dengan QuerySet
1. Mengubah isi file views.py
```
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView, ListView
from .models import Event
def events_listview(request):
template_name = 'events/templates/events/events_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class EventListView(ListView):
template_name = 'events/events_list.html'
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
```
2. Mengubah isi file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/(?P<slug>\w+)/$', EventListView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
3. Cek melalui browser

filter pada Fancon:

filter pada Event:

filter pada Concert:

---
### **6. Profile Detail**
DetailView berfungsi untuk menampilkan detail dari satu objek model. Misalnya menampilkan detail dari satu detail produk dalam toko.
1. Mengedit file event_detail.html di dalam direktori /events/templates/events/
```
{% extends "base.html" %}
{% block head_tittle %}Event || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>{{ object.name }} <small> {{ object.artist }}</small></h1>
<p>Category: {{ object.category }}</p>
<p>Location: {{ object.location }}</p>
<p>Held on : {{ object.Event_date }}</p>
<p>Add on : {{ object.timestamp }}, Updated {{ object.update|timesince }} ago</p>
{% endblock %}
```
2. Mengedit file views.py
```
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .models import Event
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
def get_context_data(self, *args, **kwargs):
print(self.kwargs)
context = super(EventDetailView, self).get_context_data(*args, **kwargs)
print(context)
return context
```
3. Mengedit file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/(?P<pk>\w+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
4. Cek melalui browser

### **7. SlugField & Unique Slug Generator**
SlugField digunakan untuk menyimpan nilai yang dihasilkan dari judul atau teks lainnya, dimodifikasi agar sesuai untuk digunakan dalam URL. misalkan dengan mengubah huruf menjadi kecil sepenuhnya, dan mengubah spasi dengan tanda (-).
1. Mengubah file models.py
```
from django.db import models
class Event(models.Model):
name = models.CharField(max_length=120)
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(null=True, blank=True)
def __str__(self):
return self.name
@property
def title(self):
return self.name
```
2. Migrate
```
```

4. Mengubah isi file views.py
```
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .models import Event
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
def get_object(self, *args, **kwargs):
rest_id = self.kwargs.get('rest_id')
obj = get_object_or_404(Event, id=rest_id)
return obj
```
3. Membuat file utils.py di dalam direktori events
```
import random
import string
from django.utils.text import slugify
def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def unique_slug_generator(instance, new_slug=None):
if new_slug is not None:
slug = new_slug
else:
slug = slugify(instance.title)
Klass = instance.__class__
qs_exists = Klass.objects.filter(slug=slug).exists()
if qs_exists:
new_slug = "{slug}-{randstr}".format(slug=slug, randstr=random_string_generator(size=4))
return unique_slug_generator(instance, new_slug=new_slug)
return slug
```
4. generate slug melalui python shell
```
python manage.py shell
Python 3.8.2 (default, Mar 13 2020, 10:14:16)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from events.models import Event
>>> obj = Event.objects.get(id=1)
>>> from events.utils import unique_slug_generator
>>> print(unique_slug_generator(obj))
bloom
```

### **8. Unique Slug with Signal**
"Signal" digunakan untuk menanggapi peristiwa tertentu yang terjadi dalam aplikasi Django, seperti saat objek disimpan, diupdate, atau dihapus dari basis data. Signal pada objek dapat berperan untuk membuat slug, baik sebelum disimpan atau setelah disimpan.
1. Mengubah file models.py
```
from django.db import models
from django.db.models.signals import pre_save, post_save
from .utils import unique_slug_generator
class Event(models.Model):
name = models.CharField(max_length=120)
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(null=True, blank=True)
def __str__(self):
return self.name
@property
def title(self):
return self.name
def rl_pre_save_receiver(sender, instance, *args, **kwargs):
print("saving...")
print(instance.timestamp)
def rl_post_save_receiver(sender, instance, created, *args, **kwargs):
print('saved')
print(instance.timestamp)
if not instance.slug:
instance.slug = unique_slug_generator(instance)
instance.save()
pre_save.connect(rl_pre_save_receiver, sender=Event)
post_save.connect(rl_post_save_receiver, sender=Event)
```
2. Akses melalui browser

setelah diperbarui:

detail pada terminal:

---
## **Forms, Views, Models, and More**
Dalam section ini, saya membuat forms, tampilan, detail, models, dan lain sebagainya yang akan menjadi database sekaligus logika UI yang menangani project yang saya buat.
### **1. Slugs as URL Params**
Membuat slug, yang berfungsi sebagai parameter url dan membantu untuk mengarahkan url menuju object yang dimaksud. Yang mana, setiap object memiliki kode yang unik.
1. Ubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .models import Event
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
```
2. Ubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
3. Ubah file event_list.html
```
{% extends "base.html" %}
{% block head_tittle %}Events || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Events List</h1>
<ul>
{% for obj in object_list %}
<li><a href="/events/{{ obj.slug }}/">{{ obj }}</a><br/>
{{ obj.name }} by {{ obj.artist }} as a {{ obj.category }} at {{ obj.location }} held on {{ obj.Event_date }}; added on: {{ obj.timestamp }}; editted on:{{ obj.update }}.</li>
{% endfor %}
</ul>
{% endblock %}
```
4. Memastikan bahwa semua object event telah generate slug
5. Cek melalui browser


### **2. Get Single Items from DB**
Ialah cara untuk melihat suatu object secara spesifik yang diambil dari database dengan parameter tertentu, sesuai yang dibutuhkan.
1. Akses python shell
```
python manage.py shell
```
2. cek items melalui qs all
```
>>> from events.models import Event
>>> qs = Event.objects.all()
>>> qs
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event: Saranghaeyo Indonesia>, <Event: The Eternity>]>
>>> qs[1]
<Event: SU:HOME>
>>> qs.last()
<Event: The Eternity>
```

3. Cek items melalui qs filter category
```
>>> qs = Event.objects.filter(category__iexact='Concert')
>>> qs
<QuerySet [<Event: LONSDALEITE>]>
>>> qs.last()
<Event: LONSDALEITE>
```

3. Lakukan get items dengan pk
```
>>> Event.objects.get(pk=1)
<Event: BLOOM>
>>> obj = Event.objects.get(pk=1)
>>> obj.pk
1
>>> obj = Event.objects.get(pk=78)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/ubuntu/Dev/trydjango-1.11/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/ubuntu/Dev/trydjango-1.11/lib/python3.8/site-packages/django/db/models/query.py", line 378, in get
raise self.model.DoesNotExist(
events.models.DoesNotExist: Event matching query does not exist.
>>>
```

4. Ubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .models import Event
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
```
5. Mengambil item dengan get_object_or_404 melalui slug
```
>>> from django.shortcuts import render, get_object_or_404
>>> obj = get_object_or_404(Event, slug='lonsdaleite')
>>> obj
<Event: LONSDALEITE>
>>> obj = get_object_or_404(Event, slug='lonsdaleite-')
Traceback (most recent call last):
File "/home/ubuntu/Dev/trydjango-1.11/lib/python3.8/site-packages/django/shortcuts.py", line 85, in get_object_or_404
return queryset.get(*args, **kwargs)
File "/home/ubuntu/Dev/trydjango-1.11/lib/python3.8/site-packages/django/db/models/query.py", line 378, in get
raise self.model.DoesNotExist(
events.models.DoesNotExist: Event matching query does not exist.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/ubuntu/Dev/trydjango-1.11/lib/python3.8/site-packages/django/shortcuts.py", line 93, in get_object_or_404
raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
django.http.response.Http404: No Event matches the given query.
```

### **3. Saving Data the Hard + Wrong Way**
Terlalu riskan untuk memberikan akses admin kepada pengguna akhir web. Untuk itu diperlukan cara dalam mengekstrak data yang dimasukkan oleh users terdaftar. Disini, saya menggunakan POST method.
1. Membuat file forms.py di dalam direktori events dan mengubahnya
```
touch events/forms.py
...
from django import forms
class EventCreateForm(forms.Form):
name = forms.CharField(max_length=120)
artist = forms.CharField(max_length=120)
category = forms.CharField(max_length=120)
location = forms.CharField(max_length=120)
Event_date = forms.DateField()
...
```
2. Membuat file form.html di dalam direktori /events/templates/events/form.html dan mengubahnya
```
touch /events/templates/events/form.html
...
{% extends "base.html" %}
{% block head_tittle %}Add Event || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Add Event</h1>
<form method='POST'> {% csrf_token %}
<input type='text' name='name' placeholder="Event Name"><br/>
<input type='text' name='artist' placeholder="Artist"><br/>
<input type='text' name='category' placeholder="Category"><br/>
<input type='text' name='location' placeholder="Location"><br/>
<input type='date' name='Event_date' placeholder="Event Date"><br/>
<button type='submit'>Save</button>
</form>
{% endblock %}
...
```
3. Mengubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .forms import EventCreateForm
from .models import Event
def event_createview(request):
if request.method == "POST":
name = request.POST.get("name")
artist = request.POST.get("artist")
category = request.POST.get("category")
location = request.POST.get("location")
Event_date = request.POST.get("Event_date")
obj = Event.objects.create(
name = name,
artist = artist,
category = category,
location =location,
Event_date = Event_date
)
return HttpResponseRedirect("/events/")
template_name = 'events/form.html'
context = {}
return render(request, template_name, context)
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
```
atau dengan lebih singkatnya, ubah bagian event_createview menjadi sebagaimana berikut:
```
def event_createview(request):
if request.method == "POST":
form = EventCreateForm(request.POST)
if form.is_valid():
obj = Event.objects.create(
name = form.cleaned_data.get('name'),
artist = form.cleaned_data.get('artist'),
category = form.cleaned_data.get('category'),
location =form.cleaned_data.get('location'),
Event_date = form.cleaned_data.get('Event_date')
)
return HttpResponseRedirect("/events/")
if form.errors:
print(form.errors)
template_name = 'events/form.html'
context = {}
return render(request, template_name, context)
```
4. Mengubah file utils.py agar slug dapat terbuat otomatis setelah submit forms
```
import random
import string
from django.utils.text import slugify
DONT_USE = ['create']
def random_string_generator(size=10, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def unique_slug_generator(instance, new_slug=None):
if new_slug is not None:
slug = new_slug
else:
slug = slugify(instance.title)
if slug in DONT_USE:
new_slug = "{slug}-{randstr}".format(
slug=slug,
randstr=random_string_generator(size=4)
)
return unique_slug_generator(instance, new_slug=new_slug)
Klass = instance.__class__
qs_exists = Klass.objects.filter(slug=slug).exists()
if qs_exists:
new_slug = "{slug}-{randstr}".format(
slug=slug,
randstr=random_string_generator(size=4)
)
return unique_slug_generator(instance, new_slug=new_slug)
return slug
```
5. Mengubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
event_createview
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/create/$', event_createview),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
6. Cek melalui browser


atau gunakan cara yang lebih simple dengan:
1. Mengubah file views.py
```
class EventCreateViewfast(CreateView):
form_class = EventCreateFormfast
template_name = 'events/form.html'
success_url = "/events/"
```
### **4. Validating Form**
Ketika ada entri yang dilarang, maka form secara otomatis memperlihatkan kesalahan dan tidak menginput object yang dimasukkan
1. Mengubah file views.ps
```
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .forms import EventCreateForm
from .models import Event
def event_createview(request):
form = EventCreateForm(request.POST or None)
errors = None
if form.is_valid():
obj = Event.objects.create(
name = form.cleaned_data.get('name'),
artist = form.cleaned_data.get('artist'),
category = form.cleaned_data.get('category'),
location = form.cleaned_data.get('location'),
Event_date = form.cleaned_data.get('Event_date')
)
return HttpResponseRedirect("/events/")
if form.errors:
errors = form.errors
template_name = 'events/form.html'
context = {"form": form, "errors": errors}
return render(request, template_name, context)
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
```
2. Mengubah file forms.py
```
from django import forms
class EventCreateForm(forms.Form):
name = forms.CharField(max_length=120)
artist = forms.CharField(max_length=120)
category = forms.CharField(max_length=120)
location = forms.CharField(max_length=120)
Event_date = forms.DateField()
def clean_name(self):
name = self.cleaned_data.get("name")
if name == "hate":
raise forms.ValidationError("we don't need a war anymore")
return name
```
3. mengubah file form.html
```
{% extends "base.html" %}
{% block head_tittle %}Add Event || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Add Event</h1>
{% if errors %}
{{ errors }}
{% endif %}
<form method='POST'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Save</button>
</form>
{% endblock %}
```
4. Cek melalui browser

atau dengan cara yang lebih efektif
1. Mengubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView
from .forms import EventCreateFormfast
from .models import Event
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
class EventCreateViewfast(CreateView):
form_class = EventCreateFormfast
template_name = 'events/form.html'
success_url = "/events/"
```
2. Mengubah file forms.py
```
from django import forms
from .models import Event
class EventCreateFormfast(forms.ModelForm):
class Meta:
model = Event
fields = [
'name',
'artist',
'category',
'location',
'Event_date',
]
def clean_name(self):
name = self.cleaned_data.get("name")
if name == "hate":
raise forms.ValidationError("we don't need a war anymore")
return name
```
3. Mengubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
event_createview,
EventCreateViewfast
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/create/$', EventCreateViewfast.as_view()),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
4. Cek melalui browser

### **5. Simple + Effective Validation**
1. Membuat file validators.py di dalam direktori events
```
touch /events/validators.py
...
from django.core.exceptions import ValidationError
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
'%(value)s is not an even number',
params={'value': value},
)
def validate_name(value):
name = value
if name == "hate":
raise ValidationError("we don't need a war anymore")
CATEGORIES = {'Fancon', 'Concert', 'Fanmeet', 'Event', 'Promotion', 'Variety'}
def validate_category(value):
cat = value.capitalize()
if not value in CATEGORIES and not cat in CATEGORIES:
raise ValidationError(f"{value} not a valid category")
...
```
2. Mengubah file forms.py
```
from django import forms
from .models import Event
class EventCreateFormfast(forms.ModelForm):
class Meta:
model = Event
fields = [
'name',
'artist',
'category',
'location',
'Event_date',
]
```
3. Mengubah file form.html
```
{% extends "base.html" %}
{% block head_tittle %}Add Event || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Add Event</h1>
{% if form.errors.non_field_errors %}
{{ form.errors.non_field_errors }}
{% endif %}
<form method='POST'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Save</button>
</form>
{% endblock %}
```
4. Mengubah file models.py
```
from django.db import models
from django.db.models.signals import pre_save, post_save
from .utils import unique_slug_generator
from .validators import (
validate_category,
validate_name,
)
class Event(models.Model):
name = models.CharField(max_length=120, validators=[validate_name])
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120, validators=[validate_category])
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(null=True, blank=True)
def __str__(self):
return self.name
@property
def title(self):
return self.name
def rl_pre_save_receiver(sender, instance, *args, **kwargs):
instance.category = instance.category.capitalize()
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(rl_pre_save_receiver, sender=Event)
```
5. Melakukan migrate
```
python manage.py makemigrations
python manage.py migrate
```

6. Cek melalui browser


sekaligus menjadi tidak sensitif dengan huruf kapital pada category:

### **6. Letting Users own Data**
Ialah memetakan object tertentu/ yang ditambahkan ke spesifik user.
1. Ubah file models.py
```
User = settings.AUTH_USER_MODEL
class Event(models.Model):
owner = models.ForeignKey(User)
```
2. Migrate
```
python manage.py makemigrations
python manage.py migrate
```

3. Cek melalui browser

4. Akses python shell dan jalankan get_user_model
```
python manage.py shell
Python 3.8.2 (default, Mar 13 2020, 10:14:16)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.contrib.auth import get_user_model
>>> User = get_user_model()
>>> User.objects.all()
<QuerySet [<User: ubuntu>, <User: syafaa>]>
>>> ubuntu_user = User.objects.get(id=1)
>>> ubuntu_user.username
'ubuntu'
>>> ubuntu_user.event_set.all()
<QuerySet [<Event: BLOOM>, <Event: SU:HOME>, <Event: LONSDALEITE>, <Event : Saranghaeyo Indonesia>, <Event: The Eternity>, <Event: Scarlett x EXO : Glow to You>, <Event: EXO Ladder Season 4>]>
>>> syafaa_user = User.objects.get(id=2)
>>> syafaa_user.event_set.all()
<QuerySet []>
```

a. Users in FBV
1. Ubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView, CreateView
from .forms import EventCreateFormfast
from .models import Event
def event_createview(request):
form = EventCreateFormfast(request.POST or None)
errors = None
if form.is_valid():
if request.user.is_authenticated():
instance = form.save(commit=False)
instance.owner = request.user
form.save()
return HttpResponseRedirect("/events/")
else:
return HttpResponseRedirect("/login/")
if form.errors:
errors = form.errors
template_name = 'events/form.html'
context = {"form": form, "errors": errors}
return render(request, template_name, context)
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
class EventCreateViewfast(CreateView):
form_class = EventCreateFormfast
template_name = 'events/form.html'
success_url = "/events/"
```
2. Ubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
event_createview,
EventCreateViewfast
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/create/$', event_createview),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
3. Akses melalui web tanpa login user

b. User in CBV
1. Ubah file views.py
```
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView, CreateView
from .forms import EventCreateFormfast
from .models import Event
def event_createview(request):
form = EventCreateFormfast(request.POST or None)
errors = None
if form.is_valid():
if request.user.is_authenticated():
instance = form.save(commit=False)
instance.owner = request.user
form.save()
return HttpResponseRedirect("/events/")
else:
return HttpResponseRedirect("/login/")
if form.errors:
errors = form.errors
template_name = 'events/form.html'
context = {"form": form, "errors": errors}
return render(request, template_name, context)
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
class EventCreateViewfast(CreateView):
form_class = EventCreateFormfast
template_name = 'events/form.html'
success_url = "/events/"
def form_valid(self, form):
instance = form.save(commit=False)
instance.owner = self.request.user
return super(EventCreateViewfast, self).form_valid(form)
```
2. Ubah file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
event_createview,
EventCreateViewfast
)
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^events/$', EventListView.as_view()),
url(r'^events/create/$', EventCreateViewfast.as_view()),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
### **7. Login View**
Untuk meastikan keamanan object yang ditambahkan oleh pengguna, maka untuk mengakses object-object tersebut diperlukan masuk ke dalam users yang terdaftar.
1. Edit file views.py
```
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView, CreateView
from .forms import EventCreateFormfast
from .models import Event
@login_required()
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
class EventCreateViewfast(LoginRequiredMixin, CreateView):
form_class = EventCreateFormfast
login_url = '/login/'
template_name = 'events/form.html'
success_url = "/events/"
def form_valid(self, form):
instance = form.save(commit=False)
instance.owner = self.request.user
return super(EventCreateViewfast, self).form_valid(form)
```
2. Edit file urls.py
```
from django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
EventCreateViewfast
)
from django.contrib.auth.views import LoginView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html')),
url(r'^login/$', LoginView.as_view(), name='login'),
url(r'^events/$', EventListView.as_view()),
url(r'^events/create/$', EventCreateViewfast.as_view()),
url(r'^events/(?P<slug>[\w-]+)/$', EventDetailView.as_view()),
url(r'^about/$', TemplateView.as_view(template_name='about.html')),
url(r'^content/$', TemplateView.as_view(template_name='content.html')),
]
```
3. Membuat file login.html di dalam direktori /events/templates/registration/f
```
touch /events/templates/login.html
...
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% else %}
<p>Please login to see this page.</p>
{% endif %}
{% endif %}
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>
{% endblock %}
...
```
4. cek melalui browser tanpa login user
sebelum ditambahkan urls:

setelah ditambahkan urls:

### **8. Using Revers for Shortcut Urls**
Membuat shortcut url di dalam text untuk mempermudah users dalam mengakses aplikasi
1. Ubah file views.py
```
from django.db.models import Q
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView, CreateView
from .forms import EventCreateFormfast
from .models import Event
@login_required()
def events_listview(request):
template_name = 'events/event_list.html'
queryset = Event.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
def events_detailview(request, slug):
template_name = 'events/event_detail.html'
obj = Event.objects.get(slug=slug)
context = {
"object": obj
}
return render(request, template_name, context)
class EventListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = Event.objects.filter(
Q(category__iexact=slug) |
Q(category__icontains=slug)
)
else:
queryset = Event.objects.all()
return queryset
class EventDetailView(DetailView):
queryset = Event.objects.all()
class EventCreateViewfast(LoginRequiredMixin, CreateView):
form_class = EventCreateFormfast
login_url = '/login/'
template_name = 'events/form.html'
success_url = "/events/"
def form_valid(self, form):
instance = form.save(commit=False)
instance.owner = self.request.user
return super(EventCreateViewfast, self).form_valid(form)
class AboutView(TemplateView):
template_name = 'about.html'
class ContentView(TemplateView):
template_name = 'content.html'
```
2. Ubah file models.py
```
from django.db import models
from django.conf import settings
from django.db.models.signals import pre_save, post_save
from .utils import unique_slug_generator
from .validators import (
validate_category,
validate_name,
)
User = settings.AUTH_USER_MODEL
class Event(models.Model):
owner = models.ForeignKey(User)
name = models.CharField(max_length=120, validators=[validate_name])
artist = models.CharField(max_length=120)
category = models.CharField(max_length=120, validators=[validate_category])
location = models.CharField(max_length=120, null=True, blank=True)
Event_date = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(null=True, blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('events:detail', kwargs={'slug': self.slug})
@property
def title(self):
return self.name
def rl_pre_save_receiver(sender, instance, *args, **kwargs):
instance.category = instance.category.capitalize()
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(rl_pre_save_receiver, sender=Event)
```
3. Membuat file urls.py di dalam direktori events
```
touch events/urls.py
...
from django.conf.urls import url
from events.views import (
EventListView,
EventDetailView,
EventCreateViewfast
)
urlpatterns = [
url(r'^$', EventListView.as_view(), name='list'),
url(r'^create/$', EventCreateViewfast.as_view(), name='create'),
url(r'^(?P<slug>[\w-]+)/$', EventDetailView.as_view(), name='detail'),
]
...
```
4. Ubah file urls.py di dalam direktori muypicky
```
from django.conf.urls import url, include
from django.contrib import admin
from django.views.generic import TemplateView
from events.views import (
events_listview,
EventListView,
EventDetailView,
EventCreateViewfast
)
from django.contrib.auth.views import LoginView
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', TemplateView.as_view(template_name='home.html'), name='home'),
url(r'^login/$', LoginView.as_view(), name='login'),
url(r'^events/', include('events.urls', namespace='events')),
url(r'^about/$', TemplateView.as_view(template_name='about.html'), name='about'),
url(r'^content/$', TemplateView.as_view(template_name='content.html'), name='content'),
]
```
5. Ubah file nav.html
```
<div class='container'>
<h1>EXO-l.com</h1>
<a href='{% url "home" %}'>Home</a>
<a href='{% url "about" %}'>About</a>
<a href='{% url "content" %}'>Our Content</a>
<a href='{% url "events:list" %}'>Events</a>
</div>
```
6. Ubah file event_list.html
```
{% extends "base.html" %}
{% block head_tittle %}Events || {{ block.super }}{% endblock head_tittle %}
{% block content %}
<h1>Events List</h1>
<ul>
{% for obj in object_list %}
<li><a href='{% url "events:detail" slug=obj.slug %}'>{{ obj }}</a><br/>
{{ obj.name }} by {{ obj.artist }} as a {{ obj.category }} at {{ obj.location }} held on {{ obj.Event_date }}; added on: {{ obj.timestamp }}; editted on:{{ obj.update }}.</li>
{% endfor %}
</ul>
{% endblock %}
```
7. Cek melalui browser

saat masuk ke BLOOM:

saat kembali ke menu Home:

mengakses shortcut lain:

#### :bulb: Access next documentation, that i have notice before, in **[TRY DJANGO 1.11 (Database & Logic UI)](https://hackmd.io/@syafaa/TryDjango2)**