Readme and other minor updates.
parent
46a32aba7d
commit
554dcfe8b0
|
|
@ -1,2 +1,2 @@
|
|||
include LICENSE
|
||||
include README.md
|
||||
include README.rst
|
||||
|
|
|
|||
60
README.md
60
README.md
|
|
@ -1,60 +0,0 @@
|
|||
# django-database-view
|
||||
|
||||
A simple pluggable application that allows to work with database views.
|
||||
|
||||
So far only MySQL is supported as backend, but more could be added if necessary.
|
||||
|
||||
## Quick start
|
||||
|
||||
1. In your models.py create classes which extend dbview.DbView like this:
|
||||
|
||||
```python
|
||||
|
||||
from django.db import models
|
||||
from dbview.models import DbView
|
||||
|
||||
class ModelA(models.Model):
|
||||
fielda = models.CharField()
|
||||
fieldc = models.IntegerField()
|
||||
|
||||
class MyView(DbView):
|
||||
fieldA = models.OneToOneField(ModelA, primary_key=True,
|
||||
db_column='fielda__id')
|
||||
fieldB = models.IntegerField(blank=True, null=True, db_column='fieldb')
|
||||
|
||||
@classmethod
|
||||
def view(cls):
|
||||
'''
|
||||
This method returns the SQL string that creates the view, in this
|
||||
example fieldB is the result of annotating another column
|
||||
'''
|
||||
qs = modelA.objects.all().\
|
||||
annotate(fieldb=models.Sum('fieldc')) .\
|
||||
annotate(fielda__id=models.F('pk')) .\
|
||||
order_by('fielda__id') .\
|
||||
values('fielda__id', 'fieldb')
|
||||
return str(qs.query)
|
||||
```
|
||||
|
||||
Alternatively `get_view_str` method could be used to write a custom SQL:
|
||||
|
||||
```python
|
||||
|
||||
class MyView(DbView):
|
||||
|
||||
# ...
|
||||
|
||||
@classmethod
|
||||
def get_view_str(cls):
|
||||
return """
|
||||
CREATE VIEW my_view AS (
|
||||
SELECT ...
|
||||
)
|
||||
"""
|
||||
```
|
||||
|
||||
2. Then create a migration point for your view generation, edit that migration
|
||||
and modify it, add: `from dbview.helpers import CreateView` and replace the
|
||||
line the call to `migrations.CreateModel` with `CreateView`.
|
||||
|
||||
3. Migrate your database and start using your database views.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
####################
|
||||
django-database-view
|
||||
####################
|
||||
|
||||
A simple pluggable application that allows to work with database views.
|
||||
|
||||
Quick start
|
||||
===========
|
||||
|
||||
1. Install the package::
|
||||
|
||||
pip install django-database-models
|
||||
|
||||
2. In your ``models.py`` create classes which extend ``dbview.models.DbView``
|
||||
like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from django.db import models
|
||||
from dbview.models import DbView
|
||||
|
||||
class ModelA(models.Model):
|
||||
fielda = models.CharField()
|
||||
fieldc = models.IntegerField()
|
||||
|
||||
class MyView(DbView):
|
||||
fieldA = models.OneToOneField(ModelA, primary_key=True,
|
||||
db_column='fielda__id')
|
||||
fieldB = models.IntegerField(blank=True, null=True, db_column='fieldb')
|
||||
|
||||
@classmethod
|
||||
def view(cls):
|
||||
"""
|
||||
This method returns the SQL string that creates the view,
|
||||
in this example fieldB is the result of annotating another column
|
||||
"""
|
||||
qs = modelA.objects.all(
|
||||
).annotate(
|
||||
fieldb=models.Sum('fieldc'),
|
||||
).annotate(
|
||||
fielda__id=models.F('pk'),
|
||||
).order_by(
|
||||
'fielda__id',
|
||||
).values(
|
||||
'fielda__id',
|
||||
'fieldb',
|
||||
)
|
||||
return str(qs.query)
|
||||
|
||||
Alternatively ``get_view_str`` method could be used to write a custom SQL:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MyView(DbView):
|
||||
# ...
|
||||
|
||||
@classmethod
|
||||
def get_view_str(cls):
|
||||
return """
|
||||
CREATE VIEW my_view AS (
|
||||
SELECT ...
|
||||
)"""
|
||||
|
||||
3. Then create a migration point for your view generation, edit that
|
||||
migration and modify it, add:
|
||||
``from dbview.helpers import CreateView`` and replace the line the
|
||||
call to ``migrations.CreateModel`` with ``CreateView``.
|
||||
|
||||
4. Migrate your database and start using your database views.
|
||||
|
|
@ -22,7 +22,8 @@ class CreateView(migrations.CreateModel):
|
|||
elif hasattr(model, 'get_view_str'):
|
||||
self._create_view_from_raw_sql(model.get_view_str(), schema_editor)
|
||||
else:
|
||||
raise Exception(f"{model} has neither view nor get_view_str")
|
||||
raise Exception('{} has neither view nor get_view_str'.format(
|
||||
model))
|
||||
|
||||
def database_backwards(self, app_label, schema_editor, from_state, to):
|
||||
fake_model = from_state.apps.get_model(app_label, self.name)
|
||||
|
|
@ -34,7 +35,7 @@ class CreateView(migrations.CreateModel):
|
|||
if hasattr(models, self.name):
|
||||
return getattr(models, self.name)
|
||||
|
||||
# TODO: recursive search
|
||||
# TODO: identify model more reliably and support more than 1 level
|
||||
for submodule in models.__dict__.values():
|
||||
if hasattr(submodule, self.name):
|
||||
return getattr(submodule, self.name)
|
||||
|
|
|
|||
15
setup.py
15
setup.py
|
|
@ -1,15 +1,16 @@
|
|||
import os
|
||||
from setuptools import setup
|
||||
|
||||
# allow setup.py to be run from any path
|
||||
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
|
||||
|
||||
def read(fname):
|
||||
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||
|
||||
|
||||
setup(
|
||||
name='django-database-view',
|
||||
version='0.2.0',
|
||||
version='0.2.1',
|
||||
packages=['dbview'],
|
||||
setup_requires=['setuptools-markdown'],
|
||||
long_description_markdown_filename='README.md',
|
||||
long_description=read('README.rst'),
|
||||
include_package_data=True,
|
||||
license='MIT',
|
||||
description='A simple Django app to handle database views.',
|
||||
|
|
@ -29,6 +30,10 @@ setup(
|
|||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Topic :: Internet :: WWW/HTTP',
|
||||
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
|
||||
],
|
||||
|
|
|
|||
Loading…
Reference in New Issue