Readme and other minor updates.

master
murchik 2020-11-20 13:23:16 +08:00
parent 46a32aba7d
commit 554dcfe8b0
5 changed files with 83 additions and 68 deletions

View File

@ -1,2 +1,2 @@
include LICENSE include LICENSE
include README.md include README.rst

View File

@ -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.

69
README.rst 100644
View File

@ -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.

View File

@ -22,7 +22,8 @@ class CreateView(migrations.CreateModel):
elif hasattr(model, 'get_view_str'): elif hasattr(model, 'get_view_str'):
self._create_view_from_raw_sql(model.get_view_str(), schema_editor) self._create_view_from_raw_sql(model.get_view_str(), schema_editor)
else: 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): def database_backwards(self, app_label, schema_editor, from_state, to):
fake_model = from_state.apps.get_model(app_label, self.name) fake_model = from_state.apps.get_model(app_label, self.name)
@ -34,7 +35,7 @@ class CreateView(migrations.CreateModel):
if hasattr(models, self.name): if hasattr(models, self.name):
return getattr(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(): for submodule in models.__dict__.values():
if hasattr(submodule, self.name): if hasattr(submodule, self.name):
return getattr(submodule, self.name) return getattr(submodule, self.name)

View File

@ -1,15 +1,16 @@
import os import os
from setuptools import setup 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( setup(
name='django-database-view', name='django-database-view',
version='0.2.0', version='0.2.1',
packages=['dbview'], packages=['dbview'],
setup_requires=['setuptools-markdown'], long_description=read('README.rst'),
long_description_markdown_filename='README.md',
include_package_data=True, include_package_data=True,
license='MIT', license='MIT',
description='A simple Django app to handle database views.', description='A simple Django app to handle database views.',
@ -29,6 +30,10 @@ setup(
'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4', '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',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
], ],