You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+56-46Lines changed: 56 additions & 46 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,7 +22,7 @@ INSTALLED_APPS = (
22
22
)
23
23
```
24
24
25
-
## Examples
25
+
## Basic example
26
26
27
27
```python
28
28
from django.db import models
@@ -35,17 +35,14 @@ class Customer(models.Model):
35
35
post_code = models.CharField(max_length=20)
36
36
is_preferred = models.BooleanField(default=False)
37
37
38
-
classMeta:
39
-
app_label ='myapp'
40
-
41
-
classPreferredCustomer(pg.View):
42
-
projection = ['myapp.Customer.*',]
43
-
dependencies = ['myapp.OtherView',]
44
-
sql ="""SELECT * FROM myapp_customer WHERE is_preferred = TRUE;"""
38
+
39
+
classPreferredCustomer(pg.View):
40
+
name = models.CharField(max_length=100)
41
+
post_code = models.CharField(max_length=20)
42
+
43
+
sql ="""SELECT id, name, post_code FROM myapp_customer WHERE is_preferred IS TRUE"""
45
44
46
45
classMeta:
47
-
app_label ='myapp'
48
-
db_table ='myapp_preferredcustomer'
49
46
managed =False
50
47
```
51
48
@@ -59,33 +56,16 @@ CREATE VIEW myapp_preferredcustomer AS
59
56
SELECT * FROM myapp_customer WHERE is_preferred = TRUE;
60
57
```
61
58
62
-
To create all your views, run ``python manage.py sync_pgviews``
63
-
64
-
You can also specify field names, which will map onto fields in your View:
65
-
66
-
```python
67
-
from django_pgviews import view as pg
68
-
69
-
70
-
VIEW_SQL="""
71
-
SELECT name, post_code FROM myapp_customer WHERE is_preferred = TRUE
72
-
"""
73
-
59
+
To create this view, run `python manage.py migrate`, or `python manage.py sync_pgviews`.
74
60
75
-
classPreferredCustomer(pg.View):
76
-
name = models.CharField(max_length=100)
77
-
post_code = models.CharField(max_length=20)
78
-
79
-
sql =VIEW_SQL
80
-
```
61
+
Then you can query `PreferredCustomer` like any other model.
81
62
82
63
## Usage
83
64
84
-
To map onto a View, simply extend `pg_views.view.View`, assign SQL to the
85
-
`sql` argument, and define a `db_table`. You must _always_ set `managed = False`
86
-
on the `Meta` class.
65
+
To create a view, create a new class that subclasses `django_pgviews.view.View` instead of `models.Model`,
66
+
set `managed = False` on the `Meta` class, and define the `sql` class attribute with the definition of the view.
87
67
88
-
Views can be created in a number of ways:
68
+
Views can be created in two basic ways:
89
69
90
70
1. Define fields to map onto the VIEW output
91
71
2. Define a projection that describes the VIEW fields
@@ -98,20 +78,14 @@ Define the fields as you would with any Django Model:
98
78
from django_pgviews import view as pg
99
79
100
80
101
-
VIEW_SQL="""
102
-
SELECT name, post_code FROM myapp_customer WHERE is_preferred = TRUE
103
-
"""
104
-
105
-
106
81
classPreferredCustomer(pg.View):
107
82
name = models.CharField(max_length=100)
108
83
post_code = models.CharField(max_length=20)
109
84
110
-
sql =VIEW_SQL
85
+
sql ="SELECT id, name, post_code FROM myapp_customer WHERE is_preferred = TRUE"
111
86
112
87
classMeta:
113
88
managed =False
114
-
db_table ='my_sql_view'
115
89
```
116
90
117
91
### Define Projection
@@ -124,30 +98,68 @@ from django_pgviews import view as pg
124
98
125
99
126
100
classPreferredCustomer(pg.View):
127
-
projection = ['myapp.Customer.*',]
101
+
projection = ['myapp.Customer.*']
128
102
sql ="""SELECT * FROM myapp_customer WHERE is_preferred = TRUE;"""
129
103
130
104
classMeta:
131
-
db_table ='my_sql_view'
132
105
managed =False
133
106
```
134
107
135
108
This will take all fields on `myapp.Customer` and apply them to `PreferredCustomer`
136
109
110
+
## Migrations
111
+
112
+
When you run `makemigrations`, `django-pgviews` will detect changes in views and create migrations to register new views and to drop renamed or removed views.
113
+
114
+
By default, when you run `migrate`, `django-pgviews` will create or update your views – you may turn this off with `MATERIALIZED_VIEWS_DISABLE_SYNC_ON_MIGRATE`, see below.
115
+
116
+
### Autodetector
117
+
118
+
If you use another library which updates the Django migration AutoDetector, if you want to keep full functionality, you need to subclass
119
+
the AutoDetector class to subclass from `django_pgviews.db.migrations.autodetector.PGViewsAutodetector` as well.
120
+
121
+
### Changing upstream fields
122
+
123
+
If you need to change a column which is used in a view definition, you may get an error like this:
124
+
125
+
```
126
+
django.db.utils.NotSupportedError: cannot alter type of a column used by a view or rule
127
+
DETAIL: rule _RETURN on materialized view some_view depends on column "some_column"
128
+
```
129
+
130
+
To handle this, you can use the migrations to drop the view before the migration gets applied, and then recreate it afterwards.
131
+
132
+
1. Add an empty migration to the app with your view (`python manage.py makemigrations --empty app_name`)
3. Make the migration changing the column depend on the migration dropping the view
146
+
147
+
When you then run migrations, the view will be dropped, the column will be changed, and the view will be recreated by the command after all migrations are applied.
148
+
137
149
## Features
138
150
139
151
### Configuration
140
152
141
153
`MATERIALIZED_VIEWS_DISABLE_SYNC_ON_MIGRATE`
142
154
143
-
When set to True, it skips running `sync_pgview` during migrations, which can be useful if you want to control the synchronization manually or avoid potential overhead during migrations. (default: False)
155
+
When set to True, it skips running `sync_pgviews` during migrations, which can be useful if you want to control the synchronization manually or avoid potential overhead during migrations. (default: False)
144
156
```
145
157
MATERIALIZED_VIEWS_DISABLE_SYNC_ON_MIGRATE = True
146
158
```
147
159
148
160
### Updating Views
149
161
150
-
Sometimes your models change, and you need your Database Views to reflect the new data.
162
+
Sometimes your models change, and you need your views to reflect the new data.
151
163
Updating the View logic is as simple as modifying the underlying SQL and running:
152
164
153
165
```
@@ -175,8 +187,6 @@ class PreferredCustomer(pg.View):
175
187
sql ="""SELECT * FROM myapp_customer WHERE is_preferred = TRUE;"""
0 commit comments