Giter Club home page Giter Club logo

django-natural-keys's Introduction

wq

wq is a modular framework for field data collection and surveys via offline-capable mobile web apps.

Getting Started

wq can be installed via GitHub, Docker, PyPI, NPM, or a <script> tag via CDN. See the documentation for more information on getting started.

Dev Container (recommended)

  1. Go to https://github.com/wq/wq-docker-template
  2. Select "Use this template" -> "Create a new repository"
  3. Open the dev container via GitHub Codespaces or Docker Desktop

Docker Base Image

docker run ghcr.io/wq/base:main

Python

python3 -m venv venv
. venv/bin/activate
python -m pip install wq
wq create myproject

Node

npm init @wq myproject

CDN

<script type="module">
    import wq from 'https://unpkg.com/wq';
    wq.init({});
</script>

Features

wq is made up of the following submodules, which are maintained as separate packages.

Module Github PyPI npm Description
wq wq/wq wq wq Top level package (specifies submodules as dependencies)
wq.app wq/wq.app wq.app @wq/app A JavaScript+Python library for building robust offline-capable HTML5 data entry apps.
wq.build wq/wq.build wq.build wq command line interface.
wq.create wq/wq.create wq.create @wq/create Project template and scaffolding tools.
wq.db wq/wq.db wq.db Django REST framework extension with design patterns for CRUD APIs.

django-natural-keys's People

Contributors

achembarpu avatar marcosox avatar ofalk avatar realmhamdy 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

Watchers

 avatar  avatar  avatar  avatar

django-natural-keys's Issues

unique_together may be deprecated in the future - Consider Unique Constraints?

Django 2.2 introduces Unique Constraint meta option which provides greater flexibility in defining uniqueness constrains. Currently django-natural-keys does not consider Unique Constraints. According to latest (3.0) Django documentation for unique_together meta option:

Use UniqueConstraint with the constraints option instead.

UniqueConstraint provides more functionality than unique_together. unique_together may be deprecated in the future.

Therefore NaturalKeyModel should be updated to check for Unique Constraints to define natural key fields

Is rest_framework forgotten in django-natural-keys ?

Hello,

I'm discovering django-natural-keys.
It seems djangorestframework is required for loaddata/dumpdata operations.

Does it make sense to add djangorestframework as django-natural-keys dependencies ?

Best regards

AttributeError: 'Q' object has no attribute 'split'

Hi. With 1.4.0 I'm getting following error:

AttributeError: 'Q' object has no attribute 'split'

Traceback:

  File "/Users/dexter/src/gui/project/admin.py", line 179, in changelist_view
    return super().changelist_view(request, extra_context)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
    return bound_func(*args, **kwargs)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1542, in changelist_view
    self.list_max_show_all, self.list_editable, self,
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/contrib/admin/views/main.py", line 78, in __init__
    self.queryset = self.get_queryset(request)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/contrib/admin/views/main.py", line 351, in get_queryset
    qs, search_use_distinct = self.model_admin.get_search_results(request, qs, self.query)
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/django/contrib/admin/options.py", line 910, in get_search_results
    queryset = queryset.filter(reduce(operator.or_, or_queries))
  File "/Users/dexter/src/gui/.virtualenv/lib/python3.6/site-packages/natural_keys/models.py", line 8, in filter
    slugs = natural_key_slug.split(
AttributeError: 'Q' object has no attribute 'split'
>>> natural_key_slug
<Q: (OR: ('id__iexact', '9'), ('name__istartswith', '9'))>

It was after I tried to use "Search" field in list view.

AttributeError: 'CharField' object has no attribute 'rel'

Hi!

Today I upgraded my dev instance to Django 2.0 and after (of course) fixing a few things, I'm having a problem with django-natural-keys.
Exactly:

rel_to = field.rel.to if field.rel else None

For whatever reason CharObject (and probably others as well) do no longer provide the attribute 'rel'.

I've changed the code for the moment, that it looks this way:

rel_to = None
if hasattr(field, 'rel'):
    rel_to = field.rel.to if field.rel else None

But I'm not 100 % confident, that this is the (safe) way to go.

See also: AttributeError: model object has no attribute 'rel' @ Stackoverflow

Thx for

Feature request: Model __repr__

I often user natural key in my models' repr, so adding this here would be nice, something like:

'<%s: %s>' % (self._meta.model.__name__, ', '.join(self.natural_key()))

RFE: representation of datetime

The str() representation of a datetime value is s.isoformat(sep=' ') whereas the representation of a DateTimeField is s.isoformat(sep='T').

It would be nice to have the option for natural_key representation of datetime values using the latter... perhaps adding a datetime_separator variable similar to the natural_key_separator variable. Example attached.

thanks

natural_keys.models.py.txt

Use as a decorator

Requiring that a model inherit from NaturalKeyModel can conflict with other model modifiers that also requiring inheritance. It would be nice if the same functionality could be exposed via a class decorator. E.g.,

@NaturallyKeyedModel
class MyModel(SomeOtherModelSuperclass):
    # ...

Cannot run update on a non-natural field?

I am getting the following field when trying to run this code:
"NotImplementedError: Updating an existing natural key is not supported."

However, I am not trying to update the natural key.

Below is my model:
class User(BaseModel):
"""Stores the information associated with a User
first_name - The user's first name.
middle_name - The user's middle name.
last_name - The user's last name.
title - The user's official title.
eauth_id - The user's FSIS eAuth ID.
email - The user's email.
desk_phone - The user's office phone.
desk_phone_extension - The user's office phone extension.
mobile_phone - The user's personal cell phone.
home_phone - The user's home phone.
fsis_cell_phone - The user's FSIS cell phone.
status - The user's activity status.
last_login_time - The timestamp for the last successful login.
access_level - Foreign Key to ListItem Access Level.
sec_user - Foreign Key to security User.
"""

first_name = models.CharField(max_length=100)
middle_name = models.CharField(max_length=100, null=True, blank=True)
last_name = models.CharField(max_length=100)
title = models.CharField(max_length=100, null=True, blank=True)
eauth_id = models.CharField(max_length=255, unique=True)
email = models.EmailField(max_length=255)
desk_phone = models.CharField(max_length=12, null=True, blank=True)
desk_phone_extension = models.CharField(
    max_length=12, null=True, blank=True)
mobile_phone = models.CharField(max_length=12, null=True, blank=True)
home_phone = models.CharField(max_length=12, null=True, blank=True)
fsis_cell_phone = models.CharField(max_length=12, null=True, blank=True)
last_login_time = models.DateTimeField(
    null=True, blank=True)
status = models.ForeignKey(
    ListItem, related_name='user_status', on_delete=models.CASCADE)
access_level = models.ForeignKey(
    ListItem, related_name='access_level', on_delete=models.CASCADE)
sec_user = models.ForeignKey(
    SecUser, related_name='frio_user', on_delete=models.CASCADE)

def __str__(self):
    return '%s %s - %s' % (self.first_name, self.last_name, self.email)</code>

Here is my serializer:
class UserSerializer(NaturalKeySerializer):
"""Validates and serializes the User model.

Fields:
* id
* url
* created_time
* last_updated
* eauth_id
* first_name
* middle_name
* last_name
* title
* email
* desk_phone
* desk_phone_extension
* mobile_phone
* fsis_cell_phone
* status_id
* home_phone
* status_name
* status_display_text
* last_login_time
* access_level_id
* access_level_name
* access_level_display_text

"""
# The phone group requires this not_required_char to work.
not_required = {'allow_null': True, 'required': False}
not_required_char = not_required.copy()
not_required_char.update({'allow_blank': True})
phone_regex = r"^\(?[2-9]\d\d\)?-\d{3}-\d{4}$"
desk_phone = serializers.RegexField(regex=phone_regex, **not_required_char)
mobile_phone = serializers.RegexField(
    regex=phone_regex, **not_required_char)
home_phone = serializers.RegexField(regex=phone_regex, **not_required_char)
fsis_cell_phone = serializers.RegexField(
    regex=phone_regex, **not_required_char)
status_id = serializers.IntegerField(required=False)
status_name = StatusLookupField()
status_display_text = serializers.CharField(
    source='status.display_text', read_only=True)
access_level_id = serializers.IntegerField(required=False)
access_level_name = AccessLevelField(required=True)
access_level_display_text = serializers.CharField(
    source='access_level.display_text', read_only=True, required=False)
sec_user = serializers.PrimaryKeyRelatedField(read_only=True)

def validate(self, data):
    phone_fields = (
        'desk_phone',
        'mobile_phone',
        'home_phone',
        'fsis_cell_phone',
    )

    if self.instance:
        new_data = model_to_dict(self.instance)
    else:
        new_data = {}
    new_data.update(data)

    if all((new_data.get(f, '') == '' or new_data.get(f, '') is None)
            for f in phone_fields):
        raise serializers.ValidationError(
            'At least one phone is required.')

    if not (new_data.get('status') or new_data.get('status_id')):
        raise serializers.ValidationError(
            'status_id or status_name is required.')

    return data

def create(self, validated_data):
    self._link_sec_user(validated_data)
    return super(UserSerializer, self).create(validated_data)

def _link_sec_user(self, validated_data):
    """Gets or creates a SecUser with the provided eauth_id and sets it on
    the FRIO user's sec_user field."""
    eauth_id = validated_data.get('eauth_id')
    if eauth_id:
        module = USDAModule.objects.get(name='FRIO')
        sec_user, created = SecUser.objects.get_or_create(
            module=module, user_name=eauth_id)
        validated_data['sec_user'] = sec_user

def update(self, instance, validated_data):
    self._update_sec_user(instance, validated_data)
    return super(UserSerializer, self).update(instance, validated_data)

def _update_sec_user(self, instance, validated_data):
    """Updates the security user's user_name to match the eauth_id."""
    eauth_id = validated_data.get('eauth_id')
    if eauth_id and instance.sec_user.user_name != eauth_id:
        instance.sec_user.user_name = eauth_id
        instance.sec_user.save()

class Meta:
    model = models.User
    fields = ('id', 'url', 'created_time', 'last_updated',
              'eauth_id', 'first_name', 'middle_name', 'last_name',
              'title', 'email', 'desk_phone', 'desk_phone_extension',
              'mobile_phone', 'home_phone', 'fsis_cell_phone', 'status_id',
              'status_name', 'status_display_text',
              'last_login_time', 'access_level_id', 'access_level_name',
              'access_level_display_text',
              'sec_user'
              )</code>

And the code that I am trying to run that is breaking is:
user = client.frio.users.update(user['id'], {'last_login_time': cur_time})

As you can see, I am trying to update 'last_login_time' and the natural_key on that model is eauth_id. Looking at the code it seems that update is just not implemented in your code. Am I missing something?

Problem with null refs

Hi, I had a problem importing FK:s with null value. I added this code below to my class to work around.
I have a feeling though that this is not entierly correct if the Null appears on a different level??
(Ex: It fails when re-importing an existing record, calls constructor with field_id-values but constructor looks for field. Seems like constructor should never have been called.)

    def natural_key(self):
        "Override implementation to handle null refs"
        # Recursively extract properties from related objects if needed
        vals = [reduce(getattr, name_list, self) if getattr(self, name_list[0]) is not None else None
                for name_list in [name.split('__') for name in self.get_natural_key_fields()]]
        return vals

Orig impl in models.py line 215:

    def natural_key(self):
        """
        Return the natural key for this object.

        (This is a generic implementation of the standard Django function)
        """
        # Recursively extract properties from related objects if needed
        vals = [reduce(getattr, name.split('__'), self)       # Will call reduce on None
                for name in self.get_natural_key_fields()]
        return vals

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.