• 0 Oy - 0 Ortalama
  • 1
  • 2
  • 3
  • 4
  • 5
Django Forms

 
#1

Günlüğümüzde son olarak yapmak istediğimiz şey, günlük yazılarını eklemek ve düzenlemek için güzel bir yapı oluşturmak. Django'nun admin arayüzü çok havalı, ama özelleştirilmesi ve güzelleştirilmesi oldukça zor. Bunu forms (formlar) kullanarak kendi arayüzümüz üstünde mutlak bir güce sahip olacağız - neredeyse hayal ettiğimiz her şeyi yapabiliriz!

Django formlarının güzel yanı, hem sıfırdan bir form tanımlayabilmemiz hem de sonuçları modele kaydedecek bir ModelForm oluşturabilmemizdir.

Tam olarak yapmak istediğimiz şey: Post modelimiz için bir form oluşturmak.

Django'nun diğer önemli parçaları gibi, formların da kendi dosyası var: forms.py.

blog dizinimizde bu isimde bir dosya oluşturmalıyız.

Kod:
blog
└── forms.py

Tamam, hadi dosyayı açalım ve aşağıdaki kodu yazalım:

Kod:
from django import forms

from .models import Post

class PostForm(forms.ModelForm):

   class Meta:
       model = Post
       fields = ('baslik', 'yazi',)

Önce Django formları (from django import forms) ve tabii ki Post modelimizi içe aktarmalıyız (from .models import Post).

PostForm, tahmin etmiş olabileceğiniz gibi, formumuzun ismi. Django'ya bu formun bir ModelForm olduğunu belirtmeliyiz. Bunu forms.ModelForm sayesinde Django bizim için yapacaktır.

Sırada Django'ya bu formu (model = Post) oluşturmak için hangi modelin kullanılması gerektiğini anlattığımız class Meta var).

Son olarak, formumuzda hangi alan(lar)ın bulunması gerektiğini söyleyebiliriz. Bu senaryoda sadece baslik ve yazi alanlarının gösterilmesini istiyoruz - yazar şu anda giriş yapmış olması gereken kişidir (yani siz!) ve biz ne zaman yeni bir yazı oluşturursak yaratilma_tarihi otomatik olarak (örn. kod içinde) ayarlanmalıdır, değil mi?

Ve hepsi bu kadar! Şimdi tek yapmamız gereken formu bir view içinde kullanıp, template (şablon) içinde göstermek.

Bir kez daha: sayfaya bir bağlantı, bir URL, bir view ve bir template üreteceğiz.

Formun bulunduğu sayfaya bağlantı oluşturma

Şimdi blog/templates/blog/base.html şablonunu açma zamanı. Öncelikle page-header adlı div öğesinin içine bir bağlantı ekleyeceğiz:


Kod:
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>

Yeni view'i post_new olarak isimlendirdik.

Yukarıdaki satırı ekledikten sonra html dosyanız böyle görünmeli:

Kod:
{% load staticfiles %}
<html>
  <head>
       <title>Django Girls blog</title>
       <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
       <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
       <link href='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
       <link rel="stylesheet" href="{% static 'css/blog.css' %}">
   </head>
   <body>
       <div class="page-header">
           <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
           <h1><a href="/">Django Girls Blog</a></h1>
       </div>
       <div class="content container">
           <div class="row">
               <div class="col-md-8">
                   {% block content %}
                   {% endblock %}
               </div>
           </div>
       </div>
   </body>
</html>

Dokümanı kaydedip http://127.0.0.1:8000 sayfasını yeniledikten sonra, siz de tanıdık NoReverseMatch hatasını görüyor olmalısınız, değil mi?

URL

blog/urls.py dosyasını açalım ve yeni bir satır ekleyelim:

Kod:
url(r'^post/new/$', views.post_new, name='post_new'),

Ve kodun son hali şu şekilde görünecektir:

Kod:
from django.conf.urls import include, url
from . import views

urlpatterns = [
   url(r'^$', views.post_list, name='post_list'),
   url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
   url(r'^post/new/$', views.post_new, name='post_new'),
]

Sayfayı yeniledikten sonra, AttributeError şeklinde bir hata görürüz, bunun sebebi de henüz post_new view'ını (görünümünü) kodlamamış olmamız. Şimdi bu dosyayı da ekleyelim.

post_new view

Şimdi blog/views.py dosyasını açıp aşağıdaki satırları diğer from satırlarının olduğu yere ekleyelim:

from .forms import PostForm

ve bizim view'ımız:
Kod:
def post_new(request):
   form = PostForm()
   return render(request, 'blog/post_edit.html', {'form': form})

Yeni bir Post formu oluşturmak için PostForm() fonksiyonunu çağırmak ve template'e iletmek gerekir. Bu view'a geri döneceğiz, fakat öncesinde form için hızlıca bir şablon oluşturalım.

Template

Öncelikle blog/templates/blog dizininde post_edit.html isimli bir dosya oluşturmalıyız. Bir formu çalışır hale getirmek için birkaç şeye ihtiyacımız var:

form'u görüntülemeliyiz. Bunu basitçe bu şekilde yapabiliriz: {{ form.as_p }}.
yukarıdaki örnek satır HTML form etiketi içine alınmalı: <form method="POST">...</form>
bir Kaydet butonuna ihtiyacımız var. Bunu bir HTML butonu ile yapıyoruz: <button type="submit">Kaydet</button>
son olarak, hemen <form ...> etiketinden sonra {% csrf_token %} satırını eklememiz lazım. Formlarımızın güvenliğini sağladığı için bu çok önemlidir! Bunu koymayı unutup formu kaydedersek Django hata verecektir:

[Resim: csrf2.png]
Peki, şimdi de 
Kod:
post_edit.html

 in içindeki HTML kodunun nasıl görünmesi gerektiğine bakalım:



Kod:
{% extends 'blog/base.html' %}

{% block content %}
   <h1>Yeni gönderi</h1>
   <form method="POST" class="post-form">{% csrf_token %}
       {{ form.as_p }}
       <button type="submit" class="save btn btn-default">Kaydet</button>
   </form>
{% endblock %}

Yenileme zamanı! Hey! Formun görüntülendi!

[Resim: new_form2.png]

Ama, bir dakika! 

Kod:
baslik


 ve 


Kod:
yazi


 alanlarına bir şey yazıp kaydettiğimizde ne olacak?


Hiçbir şey! Yine aynı sayfaya döndük ve bütün yazdıklarımız kayboldu... ve yeni bir gönderi de eklenmemiş. Yanlış giden ne?

Yanıt: hiçbir şey. Sadece view'ımızda biraz daha iş yapmamız gerekiyor.

Formu kaydetme

Tekrar 

Kod:
blog/views.py


 dosyasını açalım. Şuan 


Kod:
post_new

 view'ı içinde sadece bunlar var:



Kod:
def post_new(request):
   form = PostForm()
   return render(request, 'blog/post_edit.html', {'form': form})

Formu kaydettiğimizde tekrar aynı view'a yönlendirileceğiz, ama bu sefer request nesnesinde, daha doğrusu request.POST (isimlendirmesinin, bizim blog uygulamasının "post" modeli ile alakası yok, gerçekte veri gönderdiğimiz (İngilizcede "post" işlemi) için isimlendirme bu şekilde) içerisinde, daha fazla verimiz olacak. HTML dosyasında <form> tanımımızdaki method="POST" değişkenini hatırlıyor musun? Formdan gelen tüm alanlar şimdi request.POST'un içerisinde. POST'un ismini değiştirmememiz lazım (method için geçerli diğer değer sadece GET'dir, ama şimdi ikisi arasındaki farkın ne olduğunu anlatacak kadar vaktimiz yok).

Oluşturduğumuz view'da iki ayrı durumu halletmemiz gerek. Birincisi: sayfaya ilk eriştiğimiz ve boş bir form istediğimiz zaman. İkincisi: henüz yazdığımız tüm form verileriyle view'a geri döndüğümüz zaman. Yani bir koşul eklememiz gerekiyor (bunun için if kullanacağız).

Kod:
if request.method == "POST":
   [...]
else:
   form = PostForm()

Şimdi boşluğu [...] doldurma zamanı geldi. method, POST ise o zaman PostFormu verilerle oluşturmamız lazım, değil mi? Bunu yapmak için:
Kod:
form = PostForm(request.POST)

Çok kolay! Şimdi de formu (yani tüm gerekli alanların doldurulduğu ve hatalı değerlerin kaydedilmeyeceğini) kontrol etmemiz lazım. Bunu da form.is_valid() ile yapıyoruz.

Formun doğruluğunu kontrol ediyoruz ve doğru ise kaydedebiliriz!
Kod:
if form.is_valid():
   post = form.save(commit=False)
   post.yazar = request.user
   post.yayinlanma_tarihi = timezone.now()
   post.save()


Temel olarak, burada iki şey yaptık: formu form.save ile kaydettik ve bir yazar ekledik (PostForm'da bir yazar tanımlı olmadığı ve bu zorunlu bir alan olduğu için!). commit=False, Post modelini henüz kaydetmek istemediğimizi belirtir - ilk önce yazarı eklemek istiyoruz. Genellikle form.save(), commit=False olmadan kullanacaksınız, ama bu durumda, bunu kullanmamız gerekiyor. post.save() değişiklikleri (yazarı ekleme) koruyacaktır ve yeni bir blog gönderisi oluşturulur!

Hemen post_detail sayfasına gidip yeni yaratmış olduğumuz blog postunu görsek harika olur, degil mi? Bunu yapabilmek için önemli bir şey daha lazım:

from django.shortcuts import redirect
Bunu dosyanın en başına ekleyelim. Şimdi yeni yarattığımız blog postu için post_detail sayfasına gidebiliriz.

   return redirect('post_detail', pk=post.pk)
post_detail gitmek istediğimiz görünümün ismidir. Unutmayalım ki bu view için bir pk değişkeni lazım. Bu değeri görünümlere aktarmak için pk=post.pk yazarız. Burada post yeni yarattığımız blog postudur!

Çok şey söyledik ama herhalde view u tümüyle bir görmek isteriz artık, değil mi?


Kod:
def post_new(request):
   if request.method == "POST":
       form = PostForm(request.POST)
       if form.is_valid():
           post = form.save(commit=False)
           post.yazar = request.user
           post.yayinlanma_tarihi = timezone.now()
           post.save()
           return redirect('post_detail', pk=post.pk)
   else:
       form = PostForm()
   return render(request, 'blog/post_edit.html', {'form': form})yazar


Bakalım çalışacak mı? http://127.0.0.1:8000/post/new/ sayfasına gidip bir `baslik` ve `yazi` ekleyelim, sonra da kaydedelim... ve işte! Yeni blog postu eklenmiş ve `post_detail` sayfasına yönlendirildik!

Postu kaydetmeden önce yayin tarihine değer atandığını fark etmiş olabilrsin. Daha sonra *yayınla butonu* nu **Django Girls Tutorial: Ek konular** da anlatacağız.

Süper!

## Form doğrulama

Şimdi de Django formlarının ne kadar havalı olduğunu görelim. Bir blog postunun `baslik` ve `yazi` alanları olmalı. `Post` modelimizde bu alanlar mecburi değil demedik ( `yayinlanma_tarihi` demiş olduğumuz gibi), dolayısı ile Django bu alanlara değer atanması gerektiğini varsayar.

`baslik` veya `yazi` olmadan formu kaydetmeye çalışın. Ne olacak, tahmin et!

![Form doğrulama][3]

[3]: images/form_validation2.png

Django tüm alanlara doğru tür değerlerin atandığını bizim için kontrol ediyor. Ne güzel, değil mi?

> Yakın zamanda Django'nun admin arayüzünü kullandığımız için, sistem bizi hala oturumda varsayıyor. Bazı durumlar bizim oturumdan çıkmamıza neden olabilir (web tarayıcısını kapatmak, veritabanını tekrar başlatmak, vb). Eğer oturumda olan kullanıcı olmadığı için post yaratmada hata alırsak admin sayfası olan http://127.0.0.1:8000/admin gidip tekrar bir oturum açmalıyız. Bu durumu geçici de olsa da halleder. Kalıcı çözüm, ana tutorialdan sonra **Ödev: Web sitene güvenlik ekleme!** bölümünde anlatılacak.

![Oturum hatası][4]

[4]: images/post_create_error.png

## Form düzenleme

Artık yeni bir form oluşturmayı biliyoruz. Peki, mevcut bir formu güncellemek için ne yapmalı? Demin yaptığımıza çok benziyor. Şimdi, hızlıca bir kaç şey yaratalım (anlamadığın bir şey olduğu zaman, mentöre veya önceki bölümlere danışabilirsin, çünkü bu adımları daha önce yaptık).

`blog/templates/blog/post_detail.html` dosyasını açıp şu satırı ekleyelim:

```python
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>

ki template buna benzesin:



Kod:
{% extends 'blog/base.html' %}

{% block content %}
   <div class="post">
       {% if post.yayinlanma_tarihi %}
           <div class="date">
               {{ post.yayinlanma_tarihi }}
           </div>
       {% endif %}
       <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
       <h1>{{ post.baslik }}</h1>
       <p>{{ post.yazi|linebreaks }}</p>
   </div>
{% endblock %}

blog/urls.py dosyasına şu satırı ekleyelim:

url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'),
Daha önce kullandığımız blog/templates/blog/post_edit.html template'i tekrar kullanacağız, tek eksik bir view.

Şimdi blog/views.py dosyasını açıp en sonuna şu satırı ekleyelim:

Kod:
def post_edit(request, pk):
   post = get_object_or_404(Post, pk=pk)
   if request.method == "POST":
       form = PostForm(request.POST, instance=post)
       if form.is_valid():
           post = form.save(commit=False)
           post.yazar = request.user
           post.yayinlanma_tarihi = timezone.now()
           post.save()
           return redirect('post_detail', pk=post.pk)
   else:
       form = PostForm(instance=post)
   return render(request, 'blog/post_edit.html', {'form': form})

Bu nerdeyse bizim post_new view'e benziyor, değil mi? Ama, tam da değil. İlk önce: Url'den ekstra bir pk parameteresi yolladık. Sonra: güncellemek istediğimiz Post modelini get_object_or_404(Post, pk=pk) ile alıp, bir form yarattığımızda bu postu bir örnek kopya (instance) olarak hem formu kaydettiğmizde yolluyoruz:

form = PostForm(request.POST, instance=post)
hem de güncellemek istediğimiz postu görmek için form açtığımız zaman yolluyoruz:

form = PostForm(instance=post)
Haydi, deneyelim. Bakalım çalışacak mı? post_detail sayfasına gidelim. Sağ üst köşede bir edit (güncelleme) butonu olmalı:


[Resim: edit_button2.png]
Butona tıklarsak blog postunu görmemiz lazım:
[Resim: edit_form2.png]
İstediğimiz gibi başlık ve yazıyı değiştirebilir ve sonra da kaydedebilriz!
Tebrikler! Uygulaman gittikçe tamamlanıyor!
Django formları hakkında daha fazla bilgi bulmak için https://docs.djangoproject.com/en/1.10/topics/forms/ adresindeki dokümanlara bakabilirsin

Güvenlik

Bir bağlantıya (link) tıklayarak yeni bir blog oluşturabilmek harika! Ancak, şu haliyle siteye gelen herkes bir blog yaratıp kaydedebilir. Bu da istenen bir durum değil. Butonun sadece sana görünmesini sağlayalım.


blog/templates/blog/base.html dosyasında yarattığımız page-header div ve anchor etiketlerini (tags) bulalım. Şuna benziyor olmalı:

<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
Şimdi bir {% if %} etiketi daha ekleyeceğiz ki link sadece admin olarak oturum açmış kişilere görünsün. Şimdilik, bu kişi sadece sensin! <a> etiketini şöyle değiştirelim:

Kod:
{% if user.is_authenticated %}
   <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
{% endif %}

Bu {% if %} linkin tarayıcıya ancak kullanıcı oturum açmış ise gönderilmesini sağlar. Bu yeni post yaratılmasını kesin olarak engellemese de iyi bir başlangıç. Güvenlik konusu ek derslerde daha çok ele alınacak.

Oturum içi olduğumuz için, şimdi sayfayı yenilersek, farklı bir şey görmeyeceğiz. Sayfayı farklı bir tarayıcıda veya incognito bir pencerede yükleyelim. O zaman bu link görünmeyecek!

Bir şey daha: deployment (yayına alma) zamanı!

Bakalım PythonAnywhere'de calışacak mı? Tekrar yayına alalım!

İlk önce kodumuzu commit edelim, sonra Github'a push edelim


Kod:
$ git status
$ git add -A .
$ git status
$ git commit -m "Web sitesine güncelleme ve yaratma için view eklendi."
$ git push

Sonra bir PythonAnywhere Bash konsol una gidip:

Kod:
$ cd ilk-blogum
$ source myvenv/bin/activate
(myvenv)$ git pull
[...]
(myvenv)$ python manage.py collectstatic
[...]

  • Nihayet, Web tab ına gidip Reload edelim.
O kadar! Tebrikler Smile



Bul
Alıntı


Benzer Konular...
Konu: Yazar Cevaplar: Gösterim: Son Mesaj
  Visual Studio'da Django soğanolsunmu 0 1,883 16-11-2018, Saat: 00:11
Son Mesaj: soğanolsunmu
  Django Uygulamalarımızı uWSGI ve Nginx ile Google Cloud Platformdan nasıl yayınlarız? poyraz 0 2,872 01-12-2017, Saat: 23:42
Son Mesaj: poyraz
  DJANGO İÇİN AMAZON ÜCRETSIZ SUNUCULARI xray 0 2,211 01-12-2017, Saat: 22:54
Son Mesaj: xray
  Django Hızlı ve Basit Site Yayınlama – Djeasy xray 0 2,848 01-12-2017, Saat: 21:03
Son Mesaj: xray
  Ubuntu 16.04 Üzerine Django 1.10.1 Nasıl Yüklenir? efsane 0 2,231 12-11-2017, Saat: 19:23
Son Mesaj: efsane

Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


Bu konuyu görüntüleyen kullanıcı(lar):
1 Ziyaretçi

   
Türkçe Çeviri: Emre KRMN, Kodlayanlar MyBB, © 2002-2024 MyBB Group.  



Merih Forum® bilgi paylaşım platformu. 2015-∞ Tüm hakları saklıdır.