Skip to content

Commit

Permalink
Merge branch 'feature/issue-48-enum-generic-relation' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
qoda committed Feb 7, 2017
2 parents b4a30d3 + 1c885ba commit 606f241
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 2 deletions.
14 changes: 14 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,23 @@ Models
- required: boolean value to indicate if the field is required
- disabled: boolean value to disable field (readonly)
- choices: a set of ``FieldChoice`` objects
- model_choices: a generic foreign key to a model which defines the choices for the formfield
- additional_validators: a set of custom defined field validators

Model Choices
~~~~~~~~~~~~~

To define a custom model for field choices the model will need to have an items related name which points to an enum items model containing key and value fields. ::

from django.db import models

class Enum(models.Model):
title = models.CharField(max_length=100)

class EnumItem(models.Model):
enum = models.ForeignKey(Enum, related_name="items")
value = models.CharField(max_length=100)
label = models.CharField(max_length=100)

Actions
~~~~~~~
Expand Down
15 changes: 15 additions & 0 deletions formfactory/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ def __init__(self, *args, **kwargs):
except TypeError:
pass

if field.model_choices and \
hasattr(field.model_choices, "items") and \
field.model_choices.items.exists():
choices = tuple(
(c.value, c.label)
for c in field.model_choices.items.all()
)
try:
if self.fields[field.slug].choices:
self.fields[field.slug].choices += choices
else:
self.fields[field.slug].choices = choices
except TypeError:
pass

try:
if field.max_length:
self.fields[field.slug].max_length = field.max_length
Expand Down
3 changes: 2 additions & 1 deletion formfactory/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ class Meta(object):
fields = [
"title", "slug", "field_groups", "field_type", "widget", "label",
"initial", "max_length", "help_text", "placeholder", "required",
"disabled", "choices", "additional_validators"
"disabled", "choices", "model_choices_content_type",
"model_choices_object_id", "additional_validators"
]


Expand Down
27 changes: 27 additions & 0 deletions formfactory/migrations/0005_added_enum_generic_relation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.1 on 2017-02-07 06:28
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('formfactory', '0004_remove_form_post_to'),
]

operations = [
migrations.AddField(
model_name='formfield',
name='model_choices_content_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'),
),
migrations.AddField(
model_name='formfield',
name='model_choices_object_id',
field=models.PositiveIntegerField(blank=True, null=True),
)
]
13 changes: 12 additions & 1 deletion formfactory/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django import forms
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _

from formfactory import actions, _registry, factory, SETTINGS, validators
Expand Down Expand Up @@ -277,6 +279,15 @@ class FormField(models.Model):
required = models.BooleanField(default=True)
disabled = models.BooleanField(default=False)
choices = models.ManyToManyField(FieldChoice, blank=True, null=True)
model_choices_content_type = models.ForeignKey(
ContentType, blank=True, null=True
)
model_choices_object_id = models.PositiveIntegerField(
blank=True, null=True
)
model_choices = GenericForeignKey(
"model_choices_content_type", "model_choices_object_id"
)
additional_validators = models.CharField(
choices=ADDITIONAL_VALIDATORS, max_length=128, blank=True, null=True
)
Expand Down
11 changes: 11 additions & 0 deletions formfactory/tests/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.db import models


class Enum(models.Model):
title = models.CharField(max_length=64)


class EnumItem(models.Model):
enum = models.ForeignKey(Enum, related_name="items")
label = models.CharField(max_length=128)
value = models.CharField(max_length=128)
14 changes: 14 additions & 0 deletions formfactory/tests/test_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import uuid

from formfactory import models
from formfactory.tests.models import Enum, EnumItem


def load_fixtures(kls):
Expand All @@ -16,6 +17,18 @@ def load_fixtures(kls):
}
kls.fieldchoice = models.FieldChoice.objects.create(**kls.fieldchoice_data)

kls.enum_data = {
"title": "Enum 1"
}
kls.enum = Enum.objects.create(**kls.enum_data)

kls.enumitem_data = {
"enum": kls.enum,
"label": "Choice 2",
"value": "choice-2"
}
kls.enumitem = EnumItem.objects.create(**kls.enumitem_data)

kls.fieldgroup_data = {
"title": "Field Group 1",
"show_title": True
Expand Down Expand Up @@ -51,6 +64,7 @@ def load_fixtures(kls):

if field_type[0] == "ChoiceField":
getattr(kls, "formfield_%s" % count).choices.add(kls.fieldchoice)
getattr(kls, "formfield_%s" % count).model_choices = kls.enum

setattr(kls, "fieldgroupthrough_data_%s" % count, {
"field_group": kls.fieldgroup,
Expand Down
4 changes: 4 additions & 0 deletions formfactory/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def test_fieldchoice(self):
for key, value in self.fieldchoice_data.items():
self.assertEqual(getattr(self.fieldchoice, key), value)

def test_modelchoices(self):
for key, value in self.enumitem_data.items():
self.assertEqual(getattr(self.enumitem, key), value)

def test_formfield(self):
for count in range(len(models.FIELD_TYPES)):
formfield_data = getattr(self, "formfield_data_%s" % count)
Expand Down

0 comments on commit 606f241

Please sign in to comment.