4 Commits 770e53981a ... b1adc789ea

Tác giả SHA1 Thông báo Ngày
  Marcos Dumay de Medeiros b1adc789ea Archiving 4 năm trước cách đây
  Marcos Dumay de Medeiros 774ddf0d17 Using Django Datetime Widget 8 năm trước cách đây
  Marcos Dumay de Medeiros 019b6a4177 More small fixes 8 năm trước cách đây
  Marcos Dumay de Medeiros 758123f1fc Radom small fixes 8 năm trước cách đây

+ 2 - 1
TODO

@@ -1,7 +1,8 @@
-Many2many does not appear in list
 Export data to csv
 Go to page number
 Filter for all basic types
 Form fields for reverse relations
+    Fix appearance of deleted forms
 Union and disjunction of permissions
 Multiple registering of actions
+Type annotations. Lots of them.

+ 7 - 6
setup.py

@@ -4,22 +4,23 @@ __author__ = 'marcos.medeiros'
 """
 
 # Always prefer setuptools over distutils
-from setuptools import setup, find_packages
+from setuptools import setup  # find_packages
 # To use a consistent encoding
 from codecs import open
 import os
 from os import path
 
+
 def _recursive_find(root, p):
     full_p = path.join(root, p)
-    for f in os.listdir(full_p):
-        full_f = path.join(full_p, f)
-        val_f = path.join(p, f)
+    for fl in os.listdir(full_p):
+        full_f = path.join(full_p, fl)
+        val_f = path.join(p, fl)
         if path.isdir(full_f):
             for ff in _recursive_find(root, val_f):
                 yield ff
         else:
-             yield val_f
+            yield val_f
 
 
 here = path.abspath(path.dirname(__file__))
@@ -81,7 +82,7 @@ setup(
     # your project is installed. For an analysis of "install_requires" vs pip's
     # requirements files see:
     # https://packaging.python.org/en/latest/requirements.html
-    install_requires=['django>=1.8', 'django-datetime-widget>=0.9', 'django-migration-fixture>=0.5', 'six'],
+    install_requires=['django==1.8', 'django-datetime-widget>=0.9', 'django-migration-fixture>=0.5', 'six'],
 
     # List additional groups of dependencies here (e.g. development
     # dependencies). You can install these using the following syntax,

+ 2 - 2
src/rapid/forms.py

@@ -10,7 +10,7 @@ from django import forms
 
 from rapid.models import Profile, Application, DocumentTemplate
 from rapid.wrappers import FieldData
-from rapid.widgets import RapidReadOnly, RapidRelationReadOnly, RapidSelector
+from rapid.widgets import RapidReadOnly, RapidSelector, getRapidReadonlyRelation
 
 
 class ManageUsers(forms.ModelForm):
@@ -18,7 +18,7 @@ class ManageUsers(forms.ModelForm):
         model = Profile
         fields = '__all__'
         widgets = {
-            'application': RapidRelationReadOnly(Application),
+            'application': getRapidReadonlyRelation(Application, None),
             'name': RapidReadOnly(),
             'description': RapidReadOnly,
             'users': RapidSelector(FieldData.from_model(Profile, 'users'))

+ 23 - 4
src/rapid/rapidforms.py

@@ -8,12 +8,16 @@ from __future__ import unicode_literals
 import collections
 
 from django import forms
+from django.db import models
+from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
 from django.db import transaction
 from django.utils.encoding import force_text
+from datetimewidget import widgets as dtwidgets
 
-from rapid.widgets import RapidSelector, RapidRelationReadOnly, rapid_alternatives_widget, rapid_dependent_widget
+from rapid.widgets import RapidSelector, rapid_alternatives_widget, rapid_dependent_widget, \
+    getRapidReadonlyRelation
 from rapid.wrappers import FieldData, ModelData
 
 import gettext
@@ -114,6 +118,8 @@ class RapidDependentField(forms.Field):
 
 
 def for_model(request, model, default_relations=()):
+    hasDtWidgets = 'datetimewidget' in settings.INSTALLED_APPS
+
     default_relations = list(default_relations)
     default_relations_request = request.GET.get('default')
     widgets = []
@@ -124,12 +130,24 @@ def for_model(request, model, default_relations=()):
         default_relations_fields = [x for x, y in default_relations]
     for (x, y) in default_relations:
         f = FieldData(getattr(model, x).field, request)
-        widgets.append((x, RapidRelationReadOnly(f.related_model().model)))
+        widgets.append((x, getRapidReadonlyRelation(f.related_model().model, y)))
         default_relations_fields.append(x)
     for f in ModelData(model).local_fields():
-        if f.is_relation() and force_text(f.bare_name()) not in default_relations_fields:
-            if f.related_model().has_permission(request, 'select'):
+        if f.is_relation():
+            if force_text(f.bare_name()) not in default_relations_fields and \
+            f.related_model().has_permission(request, 'select'):
                 widgets.append((f.bare_name(), RapidSelector(f)))
+            elif force_text(f.bare_name()) in default_relations_fields:
+                pass
+        if type(f.field) == models.DateField:
+            widgets.append((f.bare_name(), dtwidgets.DateWidget(usel10n = True, bootstrap_version=3)))
+        if type(f.field) == models.DateTimeField:
+            widgets.append((f.bare_name(), dtwidgets.DateTimeWidget(usel10n = True, bootstrap_version=3)))
+        if type(f.field) == models.TimeField:
+            widgets.append((f.bare_name(), dtwidgets.TimeWidget(usel10n = True, bootstrap_version=3)))
+
+    #if force_text(model._meta.db_table) == 'testproject_singledepontest1':
+    #    import pdb; pdb.set_trace()
     # ModelForm.Meta has attributes with the same names, thus I'll rename them
     form_model = model
     form_widgets = dict(widgets)
@@ -178,6 +196,7 @@ def for_model(request, model, default_relations=()):
 
         @transaction.atomic
         def save(self, commit=True):
+
             if not commit:
                 return super(CForm, self).save(commit)
             else:

+ 3 - 2
src/rapid/registry.py

@@ -157,11 +157,12 @@ class _Registry(object):
             raise Exception("Unidentified python module registering " + str(model))
         if module_name not in registry._modules:
             if Application.objects.filter(python_name=module_name):
-                registry._modules[module_name] = Application.objects.get(python_name=module_name)
+                a = Application.objects.get(python_name=module_name)
+                registry._modules[module_name] = ModuleEntry(a.python_name, a.name)
             else:
                 a = Application(name=module_name, python_name=module_name)
                 a.save()
-                registry._modules[module_name] = a
+                registry._modules[module_name] = ModuleEntry(a.python_name, a.name)
 
         module_entry = registry._modules[module_name]
         module_entry.models.add(model)

+ 1 - 0
src/rapid/templates/rapid/bare/create.html

@@ -1,3 +1,4 @@
+{{ form.media }}
 <h2>{{object_data.model_name.title}}</h2>
 
 <form method="POST" action="" enctype="multipart/form-data">

+ 1 - 0
src/rapid/templates/rapid/bare/update.html

@@ -1,3 +1,4 @@
+{{ form.media }}
 <h2>{{object_data.model_name.title}}</h2>
 
 <form method="POST" action=""  enctype="multipart/form-data">

+ 21 - 4
src/rapid/templates/rapid/widgets/multipleDependent.html

@@ -8,16 +8,20 @@
         border-style: solid;
         padding: 1em;
     }
-    .deleted{
+    .deleted *:not(.toggle-remove){
         text-decoration: line-through;
     }
+    .included-dependent-checkbox{
+        display: none;
+    }
 </style>
 <div id="forms-for-{{ formset.prefix }}">
     {% for form in formset %}
         <div class="rapid-singledependent {{ formset.prefix }} form">
-            <input type="checkbox" class="includes_{{ formset.prefix }}"
-                   name="includes_{{ form.prefix }}" checked="true">
+            <input type="checkbox" class="includes_{{ formset.prefix }} included-dependent-checkbox"
+                   name="includes_{{ form.prefix }}" checked>
             {{ form.as_p }}
+            <input type="button" value="Remover" class="toggle-remove">
         </div>
     {% endfor %}
 </div>
@@ -29,8 +33,21 @@
     $("#add-form-in-{{ formset.prefix }}").click(function(){
         var formcount = $("#forms-for-{{ formset.prefix }}").children("div").length;
         $("#id_{{ formset.prefix }}-TOTAL_FORMS").val(formcount + 1);
-        var empty = "<div class=\"rapid-singledependent {{ formset.prefix }} form\">\n<input type=\"checkbox\" class=\"includes_{{ formset.prefix }}\" name=\"includes_{{ formset.prefix }}-__prefix__\" checked=\"true\">\n{{ formset.empty_form.as_p|jsstr }}\n<\div>";
+        var empty = "<div class=\"rapid-singledependent {{ formset.prefix }} form\">\n<input type=\"checkbox\" class=\"includes_{{ formset.prefix }} included-dependent-checkbox\" name=\"includes_{{ formset.prefix }}-__prefix__\" checked=\"true\">\n{{ formset.empty_form.as_p|jsstr }}\n<input type=\"button\" value=\"Apagar\" id=\"toggle-remove\">\n<\div>";
         $("#forms-for-{{ formset.prefix }}").append(empty.replace(/__prefix__/g, formcount));
     });
+    $("#forms-for-{{ formset.prefix }} .included-dependent-checkbox").change(function(){
+        $(this).parent().toggleClass("deleted");
+    });
+    $("#forms-for-{{ formset.prefix }} .toggle-remove").click(function(){
+        var box = $(this).parent().children(".included-dependent-checkbox")
+        var vis = box.prop("checked");
+        box.prop("checked", !vis);
+        box.parent().toggleClass("deleted");
+        if(vis)
+            $(this).prop("value", "Incluir");
+        else
+            $(this).prop("value", "Remover");
+    });
 </script>
 </div>

+ 24 - 2
src/rapid/templates/rapid/widgets/singleDependent.html

@@ -1,4 +1,4 @@
-<div>
+<div id="form-for-{{ name }}">
 <style scoped>
     .rapid-dependent{
         border-width: 1px;
@@ -9,14 +9,36 @@
     .hidden{
         display: none;
     }
+    .deleted{
+        text-decoration: line-through;
+    }
+    .included-dependent-checkbox{
+        display: none;
+    }
 </style>
-<input type="checkbox" id="includes_{{ name }}" name="includes_{{ name }}"{% if present %} checked{% endif %}>
+<input type="checkbox" class="included-dependent-checkbox" id="includes_{{ name }}"
+       name="includes_{{ name }}"{% if present %} checked{% endif %}>
 <div class="rapid-dependent {{ name }} form{% if not present %} hidden{% endif %}">
     {{ form.as_p }}
 </div>
+<input type="button" value="{% if present %}Remover{% else %}Incluir{% endif %}" class="toggle-remove">
 <script>
     $("#includes_{{ name }}").change(function(){
         $("div.{{ name }}.form").toggleClass("hidden");
     });
+    $("#form-for-{{ name }} .included-dependent-checkbox").change(function(){
+        $(this).parent().toggleClass("deleted");
+    });
+    $("#form-for-{{ name }} .toggle-remove").click(function(){
+        var box = $(this).parent().children(".included-dependent-checkbox");
+        var vis = box.prop("checked");
+        box.prop("checked", !vis);
+        if (vis) {
+            $(this).prop("value", "Incluir");
+        } else {
+            $(this).prop("value", "Remover");
+        }
+        $("div.{{ name }}.form").toggleClass("hidden");
+    });
 </script>
 </div>

+ 25 - 27
src/rapid/widgets.py

@@ -17,40 +17,40 @@ _templates_root = 'rapid/widgets/'
 
 class RapidReadOnly(widgets.Widget):
     def render(self, name, value, attrs=None):
-        hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value)
+        hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value if value else "")
         for a in attrs.keys():
             hidden += '%s="%s" ' % (a, attrs[a])
         hidden += '>'
         return '<span class="data-value">%s</span>%s\n' % (force_text(value), hidden)
 
     def value_from_datadict(self, data, files, name):
-        return data[name]
+        return data.get(name)
 
 
-class RapidRelationReadOnly(widgets.Widget):
-    def __init__(self, model, *args, **kwargs):
-        super(RapidRelationReadOnly, self).__init__(*args, **kwargs)
-        self.model = ModelData(model)
-
-    def render(self, name, value, attrs=None):
-        hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value)
-        for a in attrs.keys():
-            hidden += '%s="%s" ' % (a, attrs[a])
-        hidden += '>'
-        if hasattr(value, '__iter__'):
-            obj = self.model.default_manager().filter(pk__in=value)
-            ret = ''
-            for o in obj:
-                ret += '<span class="data-value multiple">%s</span>\n' % force_text(o)
-            ret += hidden
-            return ret
-        else:
-            obj = self.model.default_manager().get(pk=value)
-            return '<span class="data-value">%s</span>%s\n' % (force_text(obj), hidden)
-
-    def value_from_datadict(self, data, files, name):
-        return data[name]
+def getRapidReadonlyRelation(model, originator):
+    class RapidRelationReadOnly(widgets.Widget):
+        def render(self, name, value, attrs=None):
+            hidden = '<input type="hidden" name="%s" value="%s" ' % (name, value if value else "")
+            for a in attrs.keys():
+                hidden += '%s="%s" ' % (a, attrs[a])
+            hidden += '>'
+            if hasattr(value, '__iter__'):
+                obj = model.default_manager().filter(pk__in=value)
+                ret = ''
+                for o in obj:
+                    ret += '<span class="data-value multiple">%s</span>\n' % force_text(o)
+                ret += hidden
+                return ret
+            else:
+                if value:
+                    obj = model.default_manager().get(pk=value)
+                else:
+                    obj = ""
+                return '<span class="data-value">%s</span>%s\n' % (force_text(obj), hidden)
 
+        def value_from_datadict(self, data, files, name):
+            return originator
+    return RapidRelationReadOnly
 
 class RapidSelector(widgets.Select):
     """
@@ -132,7 +132,6 @@ def rapid_alternatives_widget(alternatives, selector):
     return RapidAlternativeFormsWidget
 
 
-#TODO: Finish it!
 def rapid_dependent_widget(model_data, form, has_instance, is_mutiple):
     class RapidDependentWidget(widgets.Widget):
         # What to ask:
@@ -153,7 +152,6 @@ def rapid_dependent_widget(model_data, form, has_instance, is_mutiple):
                  'form': form,
                  'present': has_instance,
                  })
-            # import pdb; pdb.set_trace()
             t = loader.get_template(_templates_root + ('multipleDependent.html' if
                                     is_mutiple else 'singleDependent.html'))
             return t.render(c)

+ 2 - 0
testproject/testproject/settings.py

@@ -40,6 +40,7 @@ INSTALLED_APPS = (
     'testproject',
     'rapid',
     'django_migration_fixture',
+    'datetimewidget',
 )
 
 MIDDLEWARE_CLASSES = (
@@ -51,6 +52,7 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'django.middleware.security.SecurityMiddleware',
+    'django.middleware.locale.LocaleMiddleware',
 )
 
 ROOT_URLCONF = 'testproject.urls'

+ 2 - 1
testproject/testproject/templates/base.html

@@ -5,11 +5,12 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>{% block title %}Rapid Test Site{% endblock %}</title>
+    <script src="{% static 'js/jquery.js' %}"></script>
     <link href="{% static 'css/bootstrap.css' %}" rel="stylesheet">
+    <script src="{% static 'js/bootstrap.js' %}"></script>
     <link href="{% static 'css/bootstrap-theme.css' %}" rel="stylesheet">
     <link href="{% static 'css/font-awesome.css' %}" rel="stylesheet">
     <link href="{% static 'css/base.css' %}" rel="stylesheet">
-    <script src="{% static 'js/jquery.js' %}"></script>
     <style>
         div#head{
             margin-top: 2em;