Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Bersenang-senang dengan Fitur Postgres Baru Django

Pos blog ini mencakup cara menggunakan ModelFields khusus PostgreSQL baru yang diperkenalkan di Django 1.8 - Bidang ArrayField, HStoreField, dan Range.

Pos ini didedikasikan untuk para pendukung luar biasa dari kampanye Kickstarter ini yang disusun oleh Marc Tamlyn, playa sejati yang mewujudkannya.


Klub Playaz?

Karena saya seorang geek yang hebat dan tidak memiliki kesempatan untuk masuk ke Klub Playaz yang sebenarnya (dan karena pada hari ke-4 Tay adalah bomnya), saya memutuskan untuk membangun Klub Playaz online virtual saya sendiri. Apa itu sebenarnya? Jaringan sosial pribadi khusus undangan yang menargetkan sekelompok kecil individu yang berpikiran sama.

Untuk posting ini, kita akan fokus pada model pengguna dan mengeksplorasi bagaimana fitur PostgreSQL baru Django mendukung pemodelan. Fitur baru yang kami maksud hanya untuk PostgreSQL, jadi jangan repot-repot mencoba ini kecuali Anda memiliki ENGINE database Anda sama dengan django.db.backends.postgresql_psycopg2 . Anda memerlukan versi>=2.5 dari psycopg2 . Aight playa, ayo lakukan ini.

Holla jika Anda dengan saya! :)



Memodelkan Perwakilan Playa

Setiap playa mendapat perwakilan, dan mereka ingin seluruh dunia tahu tentang perwakilan mereka. Jadi mari kita buat profil pengguna (alias "perwakilan") yang memungkinkan setiap playaz kita mengekspresikan individualitasnya.

Inilah model dasar untuk perwakilan playaz:

from django.db import models
from django.contrib.auth.models import User

class Rep(models.Model):
    playa = models.OneToOneField(User)
    hood = models.CharField(max_length=100)
    area_code = models.IntegerField()

Tidak ada yang spesifik untuk 1,8 di atas. Hanya model standar untuk memperluas Pengguna Django dasar, karena playa masih membutuhkan nama pengguna dan alamat email, bukan? Plus kami menambahkan dua bidang baru untuk menyimpan tudung playaz dan kode area.



Bankroll dan RangeField

Untuk sebuah playa, mengganti tudung Anda tidak selalu cukup. Playaz sering suka memamerkan uang mereka, tetapi pada saat yang sama tidak ingin orang tahu persis seberapa besar uang itu. Kita dapat memodelkannya dengan salah satu Bidang Rentang Postgres baru. Tentu saja kita akan menggunakan BigIntegerRangeField untuk memodelkan angka besar dengan lebih baik, benar?

bankroll = pgfields.BigIntegerRangeField(default=(10, 100))

Bidang rentang didasarkan pada objek Rentang psycopg2 dan dapat digunakan untuk Numerik dan DateRanges. Dengan bidang bankroll yang dimigrasikan ke database, kita dapat berinteraksi dengan bidang rentang dengan meneruskannya ke objek rentang, jadi membuat playa pertama kita akan terlihat seperti ini:

>>>
>>> from playa.models import Rep
>>> from django.contrib.auth.models import User
>>> calvin = User.objects.create_user(username="snoop", password="dogg")
>>> calvins_rep = Rep(hood="Long Beach", area_code=213)
>>> calvins_rep.bankroll = (100000000, 150000000)
>>> calvins_rep.playa = calvin
>>> calvins_rep.save()

Perhatikan baris ini:calvins_rep.bankroll = (100000000, 150000000) . Di sini kita mengatur bidang rentang dengan menggunakan tupel sederhana. Anda juga dapat menyetel nilai menggunakan NumericRange objek seperti ini:

from psycopg2.extras import NumericRange
br = NumericRange(lower=100000000, upper=150000000)
calvin.rep.bankroll = br
calvin.rep.save()

Ini pada dasarnya sama dengan menggunakan Tuple. Namun, penting untuk mengetahui tentang NumericRange objek seperti yang digunakan untuk menyaring model. Misalnya, jika kami ingin menemukan semua permainan yang bankrollnya lebih besar dari 50 juta (artinya seluruh rentang bankroll lebih besar dari 50 juta):

Rep.objects.filter(bankroll__fully_gt=NumericRange(50000000, 50000000))

Dan itu akan mengembalikan daftar playas itu. Sebagai alternatif, jika kami ingin menemukan semua permainan yang uangnya “sekitar kisaran 10 hingga 15 juta”, kami dapat menggunakan:

Rep.objects.filter(bankroll__overlap=NumericRange(10000000, 15000000))

Ini akan mengembalikan semua permainan yang memiliki kisaran bankroll yang mencakup setidaknya beberapa bagian dari kisaran 10 hingga 15 juta. Permintaan yang lebih mutlak adalah semua permainan yang memiliki bankroll sepenuhnya di antara rentang, yaitu semua orang yang menghasilkan setidaknya 10 juta tetapi tidak lebih dari 15 juta. Kueri itu akan terlihat seperti:

Rep.objects.filter(bankroll__contained_by=NumericRange(10000000, 15000000))

Informasi lebih lanjut tentang kueri berbasis Rentang dapat ditemukan di sini.



Skillz sebagai ArrayField

Ini tidak semua tentang bankroll, playaz punya skillz, semua jenis skillz. Mari kita buat modelnya dengan ArrayField.

skillz = pgfields.ArrayField(
    models.CharField(max_length=100, blank=True),
    blank = True,
    null = True,
)

Untuk mendeklarasikan ArrayField kita harus memberikan argumen pertama, yang merupakan basefield. Tidak seperti daftar Python, ArrayFields harus mendeklarasikan setiap elemen daftar sebagai tipe yang sama. Basefield mendeklarasikan tipe ini, dan dapat berupa tipe kolom model standar. Dalam kasus di atas, kami baru saja menggunakan CharField sebagai tipe dasar kami, yang berarti skillz akan menjadi array string.

Menyimpan nilai ke ArrayField persis seperti yang Anda harapkan:

>>>
>>> from django.contrib.auth.models import User
>>> calvin = User.objects.get(username='snoop')
>>> calvin.rep.skillz = ['ballin', 'rappin', 'talk show host', 'merchandizn']
>>> calvin.rep.save()

Menemukan permainan berdasarkan skillz

Jika kita membutuhkan playa tertentu dengan keterampilan tertentu, bagaimana kita akan menemukannya? Gunakan __contains filter:

Rep.objects.filter(skillz__contains=['rappin'])

Untuk pemain yang memiliki salah satu keterampilan ['rappin', 'djing', 'memproduksi'] tetapi tidak memiliki keterampilan lain, Anda dapat melakukan kueri seperti ini:

Rep.objects.filter(skillz__contained_by=['rappin', 'djing', 'producing'])

Atau jika Anda ingin menemukan seseorang yang memiliki daftar keterampilan tertentu:

Rep.objects.filter(skillz__overlap=['rappin', 'djing', 'producing'])

Anda bahkan dapat menemukan hanya orang-orang yang mencantumkan keterampilan sebagai keterampilan pertama mereka (karena semua orang mencantumkan keterampilan terbaik mereka terlebih dahulu):

Rep.objects.filter(skillz__0='ballin')



Game sebagai HStore

Game dapat dianggap sebagai daftar berbagai keterampilan acak yang mungkin dimiliki playa. Karena Game mencakup segala macam hal, mari kita buat modelnya sebagai bidang HStore, yang pada dasarnya berarti kita dapat menempelkan kamus Python lama di sana:

game = pgfields.HStoreField()

Luangkan waktu sejenak untuk memikirkan apa yang baru saja kita lakukan di sini. HStore cukup besar. Ini pada dasarnya memungkinkan untuk penyimpanan data tipe "NoSQL", tepat di dalam postgreSQL. Plus, karena di dalam PostgreSQL kita dapat menautkan (melalui kunci asing), tabel yang berisi data NoSQL dengan tabel yang menyimpan data tipe SQL biasa. Anda bahkan dapat menyimpan keduanya di tabel yang sama pada kolom yang berbeda seperti yang kita lakukan di sini. Mungkin playas tidak perlu menggunakan jankie itu, semua bicara MongoDB lagi…

Kembali ke detail implementasi, jika Anda mencoba memigrasikan bidang HStore baru ke dalam database dan berakhir dengan kesalahan ini-

django.db.utils.ProgrammingError: type "hstore" does not exist

-maka database PostgreSQL Anda adalah pra 8.1 (waktu untuk memutakhirkan, playa) atau tidak menginstal ekstensi HStore. Perlu diingat bahwa di PostgreSQL, ekstensi HStore diinstal per database dan bukan di seluruh sistem. Untuk menginstalnya dari prompt psql Anda, jalankan SQL berikut:

CREATE EXTENSION hstore

Atau jika mau, Anda dapat melakukannya melalui Migrasi SQL dengan file migrasi berikut (dengan asumsi Anda terhubung ke database sebagai pengguna super):

from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = []

    operations = [
        migrations.RunSQL("CREATE EXTENSION IF NOT EXISTS hstore")
    ]

Terakhir, Anda juga perlu memastikan bahwa Anda telah menambahkan 'django.contrib.postgres' ke 'settings.INSTALLED_APPS' untuk memanfaatkan bidang HStore.

Dengan pengaturan itu, kami dapat menambahkan data ke HStoreField kami game dengan melemparkan kamus seperti ini:

>>>
>>> calvin = User.objects.get(username="snoop")
>>> calvin.rep.game = {'best_album': 'Doggy Style', 'youtube-channel': \
    'https://www.youtube.com/user/westfesttv', 'twitter_follows' : '11000000'}
>>> calvin.rep.save()

Ingatlah bahwa dict hanya boleh menggunakan string untuk semua kunci dan nilai.

Dan sekarang untuk beberapa contoh yang lebih menarik…



Propz

Mari kita menulis fungsi "tampilkan game" untuk mencari game playaz dan mengembalikan daftar playaz yang cocok. Dalam istilah culun, kami mencari melalui bidang HStore untuk setiap kunci yang diteruskan ke fungsi. Tampilannya seperti ini:

def show_game(key):
    return Rep.Objects.filter(game__has_key=key).values('game','playa__username')

Di atas kami telah menggunakan has_key filter untuk bidang HStore untuk mengembalikan kumpulan kueri, kemudian filter lebih lanjut dengan fungsi nilai (terutama untuk menunjukkan bahwa Anda dapat merangkai django.contrib.postgres hal-hal dengan hal-hal set kueri biasa).

Nilai yang dikembalikan akan menjadi daftar kamus:

[
  {'playa__username': 'snoop',
  'game': {'twitter_follows': '11000000',
           'youtube-channel': 'https://www.youtube.com/user/westfesttv',
           'best_album': 'Doggy Style'
        }
  }
]

Seperti yang mereka katakan, Game mengenali Game, dan sekarang kita juga dapat mencari game.



Roller Tinggi

Jika kami percaya apa yang dikatakan playaz kepada kami tentang uang mereka, maka kami dapat menggunakannya untuk memberi peringkat pada mereka dalam kategori (karena ini adalah rentang). Mari tambahkan peringkat Playa berdasarkan bankroll dengan level berikut:

  • uang muda – bankroll kurang dari seratus ribu

  • balla – bankroll antara 100.000 dan 500.000 dengan keterampilan 'ballin'

  • playa – bankroll antara 500.000 dan 1.000.000 dengan dua keterampilan dan beberapa permainan

  • roller tinggi – bankroll lebih dari 1.000.000

  • O.G. – memiliki skill 'gangsta' dan kunci permainan "jadul"

Permintaan untuk balla ada di bawah. Ini akan menjadi interpretasi yang ketat, yang hanya akan mengembalikan mereka yang seluruh rentang bankrollnya berada dalam batas yang ditentukan:

Rep.objects.filter(bankroll__contained_by=[100000, 500000], skillz__contains=['ballin'])

Cobalah sisanya sendiri untuk beberapa latihan. Jika Anda memerlukan bantuan, Baca Dokumen.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tabel Pemecahan Masalah Tidak Ditemukan Kesalahan

  2. Kerentanan Injeksi SQL Joomla

  3. Driver ODBC Google BigQuery

  4. Cara Mengelompokkan Berdasarkan Tahun di SQL

  5. Cara Memangkas String di SQL