Giter Club home page Giter Club logo

wq.db's Introduction

wq.db

wq.db is a collection of Python modules for building robust, flexible schemas and REST APIs for use in creating field data collection apps and (more generally) mobile-first websites with progressive enhancement. wq.db is the backend component of wq and is geared primarily for use with wq.app, though it can be used separately. wq.db is built on the Django platform.

Latest PyPI Release Release Notes Documentation License GitHub Stars GitHub Forks GitHub Issues

Tests Python Support Django Support

Installation

API
wq Config Object โ€ข URL Structure โ€ข Settings

wq.db.rest
ModelRouter โ€ข ModelSerializer โ€ข ModelViewSet

Guides
Fieldsets โ€ข Repeating Nested Forms โ€ข Entity-Attribute-Value

wq.db's People

Contributors

davidoj avatar sheppard avatar tomaszn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wq.db's Issues

Handling of context misses for type filters

#65 introduces default behaviour when filtering attachments with a type filter: an empty context will result in the filter fields being filtered against None, which would usually result in an empty set of attachments (this could be made more robust).

The filter will fail if there is a populated context, but there is a miss on one or more of the type filter fields. In particular, the computed filter will be {'fieldname' : ''}, which raises an error if the field type is not in fact a string.

If I'm reading correctly, the behaviour consistent with wq.app would be to return an empty set of attachments in all such cases.

better handling of checkbox values

The latest version of DRF handles boolean values more robustly, but it breaks some things with how checkboxes worked before (e.g. the <input> needs to have value="t" instead of just "on"). Also, unchecking a box on an existing record doesn't necessarily cause an update to False (since the field is omitted entirely). Need a better way of handling checkbox values (here and/or in wq.app).

rest: clean up ModelSerializer.get_default_fields

The multiple interwoven use cases are getting a bit out of hand. Probably should break down and have multiple serializers for each case:

  • Detail view (retrieve/update)
  • List view (list)
  • List view post (create)
  • GeoJSON versions?

Perhaps the view should then have more specific functions like get_serializer_for_update?

Edit: The biggest issue is really the excessive magic for generating nested serializers. Instead of detail/list/etc. serializers, this can be cleaned up simply by creating explicit, custom serializers whenever a nested serializer is needed. This will likely affect the external API so is a good candidate for 0.8. See #34.

tests

It's time to integrate a testing framework.

Django REST framework requires details field

djangorestframework==3.8.2

 File "/srv/venv/lib64/python3.6/site-packages/wq/db/rest/__init__.py", line 2, in <module>
    from .routers import ModelRouter, router
  File "/srv/venv/lib64/python3.6/site-packages/wq/db/rest/routers.py", line 560, in <module>
    router = ModelRouter()
  File "/srv/venv/lib64/python3.6/site-packages/wq/db/rest/routers.py", line 49, in __init__
    initkwargs={'suffix': 'List'}
TypeError: __new__() missing 1 required positional argument: 'detail'

rest: can only register one model per model name

wq.db.rest.app.router assumes that there is only one model with a given name (as it doesn't include the app label when differentiating models). For example, if vera.Site is registered, sites.Site should not be. Should at least provide a warning when the user registers two models with the same name. Another option would be to provide a custom name for the model when registering it.

remove patterns.admin code?

It's rarely used and not tested. The wq.db.rest interface is more robust and the preferred route - it just needs some templates.

drf 3.0

Update to Django REST Framework 3.0.

don't register patterns attachment models by default?

Registering patterns attachment models by default means that they are downloaded separately by wq.app, and it's not easy to ensure the right attachments are downloaded (e.g. the first 50 "identifiers" may or may not correspond to the first 50 "mymodels"). When saving, wq.app extracts attachments from saved models and stores them in their separate list. However, it's much more common to only need to load attachments together with their parent models, and there isn't usually a need to reference attachments as a distinct list.

As of wq.db 0.8.2, the Location model is no longer registered by default and is always referenced with respect to a parent model (though locate is already a special case).

This change would likely mean including attachments even in list views (since list views are what wq.app uses to cache JSON data). We'd also need to document how to re-enable the current behavior and deal with the caveats.

Problem with saving in edit views with annotationtype models

While the creation of new model instances for an AnnotatedModel functions properly via POST request, when attempting to save via a PUT request, the server returns the following Error:

'GenericRelatedObjectManager' object is not iterable

Associated annotations for the annotated model are included in the PUT request.

__init__() missing 1 required positional argument: 'engine' loading "/"

After going through the installation procedure here:
https://wq.io/docs/setup

using ubuntu 14.04

TypeError at /
init() missing 1 required positional argument: 'engine'
Request Method: GET
Request URL:
Django Version: 1.8.2
Exception Type: TypeError
Exception Value:
init() missing 1 required positional argument: 'engine'
Exception Location: /usr/local/lib/python3.4/dist-packages/wq/db/rest/template.py in get_template_source, line 9
Python Executable: /usr/bin/python3
Python Version: 3.4.0
Python Path:
['/home/wq/proj/da/db',
'/usr/lib/python3.4',
'/usr/lib/python3.4/plat-x86_64-linux-gnu',
'/usr/lib/python3.4/lib-dynload',
'/usr/local/lib/python3.4/dist-packages',
'/usr/lib/python3/dist-packages']
Server time: Mon, 25 May 2015 16:10:39 +0000

remove support for django 1.6 and earlier

wq.db 0.7 will add support for Django 1.7 and drop support for Django 1.5. To keep the codebase clean, wq.db 0.8 should probably drop support for 1.6.

This would include:

  • Removing remaining references to south
  • Removing other compatibility hacks (field.clone()?)

set debug in config object

Add a debug entry to the router-generated config object indicating the state of settings.DEBUG. Could use router.set_extra_config for this (see wq/wq#15) though will need to make sure it's always set. This will be used by wq.app for various build settings - see wq/wq.app#45

wq.db.rest.serializers.ModelSerializer's context contains no request

My serializer should calculate some values which depend on the user's account.

I subclassed ModelSerializer (from wq), and can't find a way to reliably determine the request in the constructor (to prepare information for to_representation method to use for every serialized instance).

According to https://stackoverflow.com/a/34617511/1762343, the request should be in self.context dict, but I can only (sometimes) find 'router': <wq.db.rest.routers.ModelRouter> there.

BooleanField and NullBooleanField treated as type=string with dump_config

Survey(models.Model):
    date = models.DateField()
    valid_survey = models.BooleanField()

For such a model ./manage.py dump_config outputs string as the type of valid_survey:

            "form": [
                {
                    "name": "date",
                    "bind": {
                        "required": true
                    },
                    "type": "date",
                    "label": "Date"
                },
                {
                    "name": "valid_survey",
                    "type": "string",
                    "label": "Valid Survey"
                }
            ]

Consequently, wq maketemplates renders it as a simple text input which is not a best option.
If these two (Null)BooleanField field types were treated as type "select one", they would hopefully be rendered as choice buttons by wq maketemplates.

rest: standardize on field_id

Foreign keys are serialized as (field)_id, but when saving a model, the field name must be sent without the id suffix. Among other things, this makes form rendering a bit awkward (<input name=field value={{field_id}}>). The best approach is probably to standardize on field_id, and figure out how to remove the field_from_native / field_to_native hacks in IDRelatedField.

can't leave existing image in place if file field is required

While a file field is required, the form requires a new file and does not allow leaving the existing one in place. Should perhaps allow fields like Django's form to leave or remove existing file separate from uploading a new one.
(edit: When the file field is optional, it's possible to submit the form without a new file; the existing file stays in place and there is no way to remove it.)

no user profile information available in login.json

One of the least intrusive ways to extend the Django's User model is to create a separate model with OneToOne relation to the User model, that contains additional fields about the user (e.g. the company he belongs to).
It would be useful if the serializer could include that information at /login.json.
One solution would be to provide a configuration option "EXPOSE_USER_PROFILE_CLASSES" and use it to add related OneToOne objects recursively (e.g. to access user.profile.company.name).

Context Variables through app.router.add_page

When creating a new page with add_page, I would have expected to be able to set context variables directly for both the server-side and the config.json. Currently, creating a view as a third parameter is the only way to pass a context variable through.

It would be really handy to be able to pass variables directly through to both the config.json and the "page_name".json.

Thanks!

"This field may not be null." for models.CharField declared with blank=True

There is an inconsistency of client- and server-side validation for CharField fields with blank=True.
The generated templates accept such an object, but the synchronization fails. The outbox synchronization process sends these fields as "", but the server responds with "400 Bad Request" with a JSON structure containing "This field may not be null." messages.

remove all references to wq.db.patterns from wq.db.rest

This will require some sort of "pattern registration" api which will have a nice side effect of making it easier to register custom patterns with the rest api. It will also open up the possibility of spinning off more of the built-in patterns into separate libraries.

contrib: long-term overhaul

  • Move the thumbnail generator in files.views / files.util to a separate PyPI package
  • Make dbio a separate PyPI package (eventually) supporting arbitrary models; fully independent of vera (and possibly independent of wq.db, like django-rest-pandas is)
    • Edit: dbio relies on the identify pattern so it will still need to depend on wq.db.
  • Move vera code to the existing PyPI package
  • Probably leave chart, search and the rest of files as the remaining contrib apps.
    • Edit: Chart is dependent on vera though... fix this

update template engine to work with Django 1.8 TEMPLATE setting

I am trying to override one of the admin templates for a django app build with wq (the species tracker example app). When I add the directory to the template I am using to override the admin template, like this:

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
    os.path.join(BASE_DIR, 'db/dictionary/templates'),
)

I get this error: 'Template' object has no attribute 'nodelist'

But this works:

# TEMPLATE_DIRS = (
#     os.path.join(BASE_DIR, 'templates'),
#     # os.path.join(BASE_DIR, 'db/dictionary/templates'),
# )
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
                 os.path.join(BASE_DIR, 'db/dictionary/templates'),
                 ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            # 'loaders': [
            #     'django.template.loaders.filesystem.Loader',
            #     'django.template.loaders.app_directories.Loader',
            # ]
        },
    },

]

But in the second case, none of wq's templates render.

In django's documentation, they show how you can use multiple template backends for different folders of templates:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            '/home/html/example.com',
            '/home/html/default',
        ],
    },
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [
            '/home/html/jinja2',
        ],
    },
]

I tried something similar, but I don't know what to put in the 'BACKEND' directive for the wq templates.

What can I do differently to override the admin template using the default template backend without interfering with wq's template rendering?

rest: change autodiscover to search for a different submodule

Currently, wq.db.rest.app.autodiscover() searches for myapp.views (and myapp.serializers) to ensure registration methods are called. The choice of views makes some sense as much of the view logic is handled automatically by the router. However, it makes things a bit messy whenever one needs to actually define custom views. It would probably be best to recommend a separate namespace for registration: myapp.rest, myapp.app, or myapp.routes being some possibilities.

Django 2 support

Per Django's guidelines, this means we can also drop support for 1.8 and 1.10.

  • Limit travis, setup.py, and README to Django 1.11 and 2.0
  • Fix any failing tests
  • Review entire code to remove any remaining backwards compatibility hacks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.