Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Commit

Permalink
Added in IterField
Browse files Browse the repository at this point in the history
  • Loading branch information
dbate committed May 15, 2014
1 parent eaba8bc commit 14f86ad
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 5 deletions.
1 change: 1 addition & 0 deletions django_cookbook/model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__author__ = 'dbate'
42 changes: 42 additions & 0 deletions django_cookbook/model/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import json
from django.core.exceptions import ValidationError
from django.db.models import TextField
import re


def is_iterable(obj):
try:
iter(obj)
return True
except TypeError:
return False


class IterField(TextField):
"""
Stores the an iterable object in the the database. The data is stored as JSON and so all the values given to the
field must be serializable by the "json" module. This includes dict, list, tuple, str, int, float, True, False and
None
"""

LIST_RE = re.compile(r"\[(.*)\]")

def to_python(self, value):
if isinstance(value, list):
return value

if not isinstance(value, str):
raise ValidationError("Invalid input for a IterField instance")

if not value:
return []

# We could store the data as a string representation of the iterable which we then "eval" but this would allow
# for malicious data to be stores in the field so we need to do some sanity checking on the string. We let the
# json library handle this.
return json.loads(value)

def get_prep_value(self, value):
return json.dumps(value, separators=(',', ':'))


Empty file.
80 changes: 80 additions & 0 deletions django_cookbook/test/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""
Django settings for quokka project.
For more information on this file, see
https://docs.djangoproject.com/en/dev/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/dev/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
from django.conf.global_settings import MEDIA_ROOT
import sys

import socket

try:
HOSTNAME = socket.gethostname()
except:
HOSTNAME = 'localhost'

BASE_DIR = os.path.dirname(os.path.dirname(__file__))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '!j!rcmgm!@*zhjkq)3tl*r&&zug3&4hklo*s)#b*5_-=u0s1iw'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)

MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)



DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
}
}

# Internationalization
# https://docs.djangoproject.com/en/dev/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True
1 change: 1 addition & 0 deletions django_cookbook/test/unit/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__author__ = 'dbate'
37 changes: 37 additions & 0 deletions django_cookbook/test/unit/test_IterField_GetPrepValue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_cookbook.test.settings")

from django_cookbook.model.fields import IterField
from django.test import TestCase


class IterField_GetPrepValue(TestCase):
def test_ValueIsAnEmptyList_StringIsEmptyList(self):
field = IterField()

self.assertEqual("[]", field.get_prep_value([]))

def test_ValueIsAnEmptyDictionary_StringIsEmptyDict(self):
field = IterField()

self.assertEqual("{}", field.get_prep_value({}))

def test_ValueIsListOfElements_StringIsJsonRepresentationOfThatListWithNoSpaces(self):
field = IterField()

self.assertEqual("[1,2,3,4,5]", field.get_prep_value([1, 2, 3, 4, 5]))

def test_ValueIsListOfListsAndDictionaries_StringIsJsonRepresentationOfThatListWithNoSpaces(self):
field = IterField()

self.assertEqual("[[1,2,3],{\"4\":5}]", field.get_prep_value([[1, 2, 3], {4: 5}]))

def test_ValueIsDictionaryOfElements_StringIsJsonRepresentationOfThatListWithNoSpaces(self):
field = IterField()

self.assertEqual("{\"1\":2,\"3\":4,\"5\":6}", field.get_prep_value({1: 2, 3: 4, 5: 6}))

def test_ValueIsDictionaryOfListsAndDictionaries_StringIsJsonRepresentationOfThatListWithNoSpaces(self):
field = IterField()

self.assertEqual("{\"1\":{\"2\":3},\"4\":[5,6]}", field.get_prep_value({1: {2: 3}, 4: [5, 6]}))
40 changes: 40 additions & 0 deletions django_cookbook/test/unit/test_IterField_PrepToPython.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django.test import TestCase
from django_cookbook.model.fields import IterField


class IterField_PrepToPython(TestCase):
def test_ValueIsEmptyList_ResultMatchesInput(self):
value = []
field = IterField()

prepped = field.get_prep_value(value)
py = field.to_python(prepped)

self.assertEqual(value, py)

def test_ValueIsListWithElementsListAndDicts_ResultMatchesInput(self):
value = [1, 2, 3, [4, 5, 6], {"foo": 8}]
field = IterField()

prepped = field.get_prep_value(value)
py = field.to_python(prepped)

self.assertEqual(value, py)

def test_ValueIsEmptyDict_ResultMatchesInput(self):
value = {}
field = IterField()

prepped = field.get_prep_value(value)
py = field.to_python(prepped)

self.assertEqual(value, py)

def test_ValueIsDictWithElementsListAndDicts_ResultMatchesInput(self):
value = {"foo": 1, "bar": [2, 3, 4], "boo": {"moo": 5}}
field = IterField()

prepped = field.get_prep_value(value)
py = field.to_python(prepped)

self.assertEqual(value, py)
37 changes: 37 additions & 0 deletions django_cookbook/test/unit/test_IterField_ToPython.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_cookbook.test.settings")

from django.test import TestCase
from django_cookbook.model.fields import IterField


class IterField_ToPython(TestCase):
def test_StringIsEmpty_ReturnedValueIsEmptyList(self):
field = IterField()

self.assertEqual([], field.to_python(""))

def test_StringIsEmptyList_ReturnedValueIsEmptyList(self):
field = IterField()

self.assertEqual([], field.to_python("[]"))

def test_StringIsListWithOneField_ReturnedValueIsListWithThatField(self):
field = IterField()

self.assertEqual(["foo"], field.to_python('["foo"]'))

def test_StringIsListWithMultipleField_ReturnedValueIsListWithThoseFields(self):
field = IterField()

self.assertEqual(["foo", "bar", "boo"], field.to_python('["foo","bar","boo"]'))

def test_StringIsListWithMultipleFieldOneOfWhichIsAList_ReturnedValueIsListWithThoseFields(self):
field = IterField()

self.assertEqual(["foo", ["bar", "boo"], "moo"], field.to_python('["foo",["bar","boo"],"moo"]'))

def test_StringIsDictionary_ReturnedValueIsADictionaryWithTheCorrectFields(self):
field = IterField()

self.assertEqual({"foo": "bar", "boo": ["moo", "maa"]}, field.to_python('{"foo":"bar", "boo":["moo","maa"]}'))
12 changes: 8 additions & 4 deletions django_cookbook/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@

def get_authenticated_users(include=[], exclude=[]):
"""
Gets a lit of all the authenticated user who are in the include list and not in the exclude list
Gets a lit of all the authenticated user who are in the include list and not in the exclude list.
For example, assuming your user profile has a "friends" property to get all authenticated friends you would use:
:param include:
:param exclude:
:return:
>>> get_authenticated_users(include=user.friends, exclude=[user])
:param include: A list of users to include, if False no include filter is applied
:param exclude: A list of users to exclude
:return: A query set containing all authenticate uses in
"""
# get the ids of the authenticated sessions
sessions = Session.objects.filter(expire_date__gte=datetime.now())
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
setup(
name='django_cookbook',
version='0.0.1',
packages=['django_cookbook', 'django_cookbook.templatetags'],
packages=['django_cookbook', 'django_cookbook.templatetags', 'django_cookbook.model'],
url='',
license='',
author='',
Expand Down

0 comments on commit 14f86ad

Please sign in to comment.