Skip to content

Instantly share code, notes, and snippets.

@WoodProgrammer
Last active June 28, 2017 12:54
Show Gist options
  • Save WoodProgrammer/cef18a6bbdd87a4e5a1b618ea9be12f7 to your computer and use it in GitHub Desktop.
Save WoodProgrammer/cef18a6bbdd87a4e5a1b618ea9be12f7 to your computer and use it in GitHub Desktop.

SESSION VERISI ve CART MANTIĞI

  • SESSION yapısı ana mantık olarak şu şekilde çalışır.User login olur ve user'ın logout olana kadar ya da servisin işleyişine göre işlemin bitme anında , belki bir TRANSACTION COMMIT'inde,belki de logout sırasına kadar yaptığı işlemleri istediğiniz şekilde serialize edebildiğiniz bir mantık üzerine tutmaktadır.
  • SESSION işlemlerini gerçekleştirmek için Django frameworkünde arka planda sizin için birçok method çalışmakta hatta migrations'ta sizin için otomatik olarak session oluşturmakta ve bunu sizin isteğinize bağlı tutmakta.Yani Session django da da bir model gibi db'de yeri vardır.

Django Session Yapısı

  • Postgresql'de görüldüğü üzere django bize hazır migration sayesinde bir session tablosu oluşturmuş.
  • Burada görülen session_id cookie içerisinde gömülmüş vaziyette bulunmaktadır.Aynı zamanda Session tablomuz veriyi kript edilmiş halde tutmaktadır.
CREATE TABLE "django_session" (
    "session_key" varchar(40) NOT NULL PRIMARY KEY,
    "session_data" text NOT NULL,
    "expire_date" datetime NOT NULL
);
  • Pyton levelinde Session verisi ile oynamanız gerekirse verileri aşağıdaki şekilde pull edip decrypt edebilirsiniz
from django.contrib.sessions.models import Session
   
    sess = Session.objects.get(pk='session_key')
    print(sess.session_data)
    print(sess.get_decoded())

Bu methodlar djangoda Session olayları nasıl dönmektedir.Ona dair genel birkaç bilgi içermektedir. Bu nedenle ilerleyen sayfalarda daha fazla anlatılmayacak ve projede nasıl kullanıldığına odaklanılacaktır. Daha fazla bilgi için : DjangoSessionİçinTıklayınız

CART MANTIĞI

  • CART yapısında session kullanımı bir e-ticaret sitesindeki en büyük yardımcılarından bir tanesi. Eğer session ile cart kullanmasaydık.Her bir cart isteğini veritabanına yazdırsaydık ve onları Sales tablosunda yazdırıp sonra CART table da silmeler yapsaydık bu ciddi bir performans kaybına neden olurdu.
  • Burada /cart/shop/ sayfasından gelen requestler parse edilmektedir.
  • Ardından 'game' ve 'count' adında iki adet session objesi meydana gelmektedir.
def cart_status(request):
....
..
.
    try:
        request.session["game"] += ',' + request.POST.get("game")
        request.session["count"] += ',' + request.POST.get("count")
  • Ama django da session oluştururken var olmayan tipi tanımlanmamış bir key kullanımında sorun çıkartmakta. Biz de bu sorunu try except kullanarak çözdük.

  • İlk başta POST isteğini parse ediyor. Ardından session'lara ekleme yapmaya çalışıyor yapamassa except bloğunda tanımlayıp işlemi bitiriyor.

except Exception as e:
        request.session["game"] =' '
        request.session["count"] =' '
        request.session["game"] += ',' + request.POST.get("game")
        request.session["count"] += ',' + request.POST.get("count")
        
   # print(request.session['game'])
    return HttpResponseRedirect('games/games/')

Burada session datasını alıp yerine yapıştırdık ancak serialize etmekte problemler yaşıyoruz. Burada ise

views.py'daki json_converter kullanımı devreye girmekte.

Kullanımı:

Json converterda iki parametre geçiyoruz.

  • keys ise request.session['game']'i tutmakta
  • values ise request.session['game']'i tutmakta Her bir keys ile values'i match edip sonuç olarak bir json bize generate etmektedir.

Test Case

def json_converter(keys,values):
        //codes

keys = 'test_1,test_2,test3'
values = 'val1, al2,val3'

json_converter(keys,values)

Çıktısı :

        { "test_1":"val1", "test_2":" al2", "test3":"val3"}

Şimdi bu çıktığı normal python3 parse edebiliyor mu bakalım.

import json
json_file = open('test.json','r+')
j = json.loads(json_file.read())
print(j['test_1'])
  • Yukarıdaki kod parçacığı çalışınca herhangi exception vermeden şöyle bir sonuç çıkmaktadır : ' val1 '. Testleri geçen bu kod parçacığını sessiondaki cart verisi serialize edeceğimiz noktada kullanacağız.
def games(request):
    //codes
        
        return render_to_response('index.html',{'cart_datas':json_converter(my_keys.split(','),my_vals.split(','))})

Sessiondaki cart verisi json ile serialize edilmektedir burada ve test için bu değer return edilmektedir.

return render_to_response('index.html',{'cart_datas':json_converter(my_keys.split(','),my_vals.split(','))}) 

TRPIN

Türkiye'de online oyun topluluklarını hedefleyen bir e-pin satış servisi.

Bağımlılıklar

  • django 1.10.5

  • postgresql 9.5

  • Python 3.6 Öncelikle bizler geliştirme ortamı olarak PyCharm IDE'sini ve UNIX tabanlı bir işletim sistemi tercih ediyoruz. Versiyonlamak ve projeye destek olmak için

  • Linux , MacOS ve Windows(gitshell) :

    $ git clone https://github.com/WoodProgrammer/gamer_trnet.git 

VERİ TABANI (PostgreSQL 9.5)

  • Kendi yerel geliştirme ortamımızda veri tabanı olarak PostgreSql ile etkileşimi sağlamak için:
    $ cd gamer_trnet/epin/epin
  • epin klasörü içerisinde bulunan yine epin klasörü içerisinde settings.py adı verilen bir Django geliştirme ortamımız için bize config görevi gören bir dosya.Burada
DATABASES = {
   'default': {
       'ENGINE': 'django.db.backends.postgresql_psycopg2',
       'NAME': VERİ_TABANI_ADI ,
       'USER': KULLANICI_ADI,
       'PASSWORD': PAROLA,
       'HOST': VERI_TABANI_SUNUCUSUNUN_BULUNDUGU_IP,
       'PORT': PORT_NUMARASI,
   }
}
  • Port numarası varsayılan olarak 5432 olarak belirtilmiştir.Ancak portta IN_ADDR_USE tarzı bir exception almamak için varsayılan sistemde 5432 portunun kullanıp kullanılmadığını anlamak için terminale kopyalayıp yapıştırın.
 $ cat /etc/services | grep 5432 | awk '{print $2}'
  • Eğer kullanım altında ise kapatın yoksa port numaranızı değiştirin.

  • Port kontrollerini yapıp database için config ayarlarını hallettikten sonra migration işlemlerine yani tabloların veri tabanına ORM ile aktarımı kısmına gelelim. Öncelikle bulunduğumuz dizini kontrol edelim.

  $ pwd
  $ /gamer_trnet/epin ##manage.py bu klasörün altında.

Şimdi manage.py ile migration işlemlerimizi halledelim.

  $ python3 manage.py makemigrations  
  $ python3 manage.py migrate 

Bir hata olmaması durumunda modellerinizi,ve config dosyalarınızı kontrol ediniz.

 $ psql 
 emirozbir=# \l
                                            List of databases
            Name            |   Owner   | Encoding |   Collate   |    Ctype    |    Access privileges    
----------------------------+-----------+----------+-------------+-------------+-------------------------
 casino_locator             | developer | UTF8     | tr_TR.UTF-8 | tr_TR.UTF-8 | 
 datanut_development        | developer | UTF8     | tr_TR.UTF-8 | tr_TR.UTF-8 | 
 datanut_development2       | developer | UTF8     | tr_TR.UTF-8 | tr_TR.UTF-8 | 
 developer                  | developer | UTF8     | tr_TR.UTF-8 | tr_TR.UTF-8 | 
 game_trnetdb               | developer | UTF8     | tr_TR.UTF-8 | tr_TR.UTF-8 | =Tc/developer   

Postgre'de game_trnetdb'nin oluştuğunu görmekteyiz.Daha iyi bir sağlama yapabilmek için tablolarımızın durumuna bakalım

game_trnetdb=# \connect game_trnetdb
You are now connected to database "game_trnetdb" as user "emirozbir".
game_trnetdb=# \d
                         List of relations
 Schema |               Name                |   Type   |   Owner   
--------+-----------------------------------+----------+-----------
 public | auth_group                        | table    | developer
 public | auth_group_id_seq                 | sequence | developer
 public | auth_group_permissions            | table    | developer
 public | auth_group_permissions_id_seq     | sequence | developer
 public | auth_permission                   | table    | developer
 public | auth_permission_id_seq            | sequence | developer
 public | users_sale                        | table    | developer
 public | users_sale_id_seq                 | sequence | developer
 public | users_userprofile                 | table    | developer
 public | users_userprofile_id_seq          | sequence | developer
 

NOT:

Burada veritabanında tablolarımızın oluşturulduğunu görmekteyiz.Artık veritabanımız hazır hiçbir sorun olmadan yolumuza devam edebiliriz.Olası bir kolon ekleme çıkarmada ise models.py dosyamızda class'lara yeni instance'lar eklemiş olursak veya varolanları çıkartmış olursak bunların ORM tarafı bir yana veri tabanının iç kısmında bir karşılığının olması gereklidir.Yoksa application server ayağa kalkmaz. Yani her instance değişiminde.

    $ python3 manage.py makemigrations  
    $ python3 manage.py migrate 

VERİ TABANI MODELLERİ

Biz veritabanımızda temel olarak tek bir app üzerinden 5 model ile çalışmaktayız.Modellerimiz:

*  Genre #Oyunların türleri için.
*  Profile #User class'ından çekilmekte (bu konuya değineceğiz).
*  Game
*  Sale 
*  Log #Kullanılmamakta(şimdilik)

ORM KULLANMADAN EMPTY MIGRATIONS MODELİ OLUŞTURMAK

* Django da native sql kullanacağımız zaman öncelikle boş bir migration oluşturmamız gerekiyor.

* Bunun için de terminalde manage.py ile entegra edelim
          
* Ardından migrations klasöründe 0001_custom_models.py adından bir dosya oluşturuldu.
   0001_custom_models.py görüntüsü aşağıdaki gibidir.

DJANGO MIGRATION MODELİ

from __future__ import unicode_literals                                                                                                                                                      
from django.db import migrations                                                                                                                                                                  
class Migration(migrations.Migration):
      dependencies = [
        ('custom_models', '0001_initial'),
              ]
       operations = [                                                                                                                    migrations.RunSQL(''' 
                         ## USERS TABLOSU
                         create table users(
                                      id serial not null primary key,
                                      username varchar(15) not null UNIQUE,
                                      password text not null,
                                      email text not null UNIQUE,
                                      c_date timestamp default current_timestamp,full_name varchar(40) , 
                                      status boolean not null default true,balance real not null default 0,
                                      lastlogin timestamp not null default current_timestamp,
                                      admin boolean not null default false
                         );
                         ##GENRE TABLOSU
                         create table genre(
                                      id serial not null primary key,
                                      name varchar(40) not null UNIQUE
                         );
                        ##GAME TABLOSU
                         create table game(
                                      id serial not null primary key,
                                      name varchar(100) not null UNIQUE,
                                      price real not null CHECK (price > 0),
                                      popularity int not null,
                                      created_date timestamp not null default current_timestamp,
                                      update_date timestamp not null default current_timestamp,
                                      logo varchar(200),
                                      genre_id int not null references genre(id)
                          );
                          ##SALE TABLOSU
                          create table sale(
                                      id serial not null primary key,
                                      user_id int not null references users(id),
                                      game_id int not null references game(id),
                                      c_date timestamp default current_timestamp,
                                      amount real not null CHECK (price > 0)
                          );

    ''')                                                                                
    ]

USER SALE GAME İlişkisi

  • User tablosu ile Sale tablosu birbirine one to many şeklinde bağlı.Yani bizim ana bakmamız gereken durum bir user birden fazla Sale oluşturabilir.

Game ve Sale Tabloları Arasındaki İlişkisellik

  • Aynı şekilde bir ilişki daha Game ile Sales arasında burada ise 1'den çoğa ilişki mevcut yani bir user birden fazla oyun alabilir ve aynı zamanda bir oyun birden fazla sipariş Id'sine sahip olabilmesini sağlamaktadır.

  • Çoktan çoğa bir ilişki gözlenmektedir.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment