├── .gitignore ├── Procfile ├── README.md ├── app.json ├── bootstrap3 ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ └── bootstrap3 │ │ ├── base.html │ │ └── index.html ├── tests.py └── views.py ├── bootstrap4 ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ └── bootstrap4 │ │ ├── base.html │ │ └── index.html ├── tests.py └── views.py ├── django_rendering ├── __init__.py ├── templates │ └── django_rendering │ │ └── index.html └── views.py ├── manage.py ├── requirements.txt ├── semantic ├── __init__.py ├── admin.py ├── forms.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ └── semantic │ │ ├── base.html │ │ └── index.html ├── tests.py └── views.py └── test_project ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/python,django 2 | 3 | ### Python ### 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | # PyBuilder 61 | target/ 62 | 63 | 64 | ### Django ### 65 | *.log 66 | *.pot 67 | *.pyc 68 | __pycache__/ 69 | local_settings.py 70 | 71 | 72 | /db.sqlite3 73 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn test_project.wsgi --log-file - 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Crispy Test Project 2 | Simple Django project for testing [django-crispy-forms](https://github.com/maraujop/django-crispy-forms) based on [an awesome gist](https://gist.github.com/maraujop/1838193) by [@maraujop](https://github.com/maraujop). 3 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crispy-test-project", 3 | "scripts": { 4 | }, 5 | "env": { 6 | }, 7 | "addons": [ 8 | 9 | ], 10 | "buildpacks": [ 11 | { 12 | "url": "https://github.com/heroku/heroku-buildpack-python" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /bootstrap3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/bootstrap3/__init__.py -------------------------------------------------------------------------------- /bootstrap3/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /bootstrap3/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django import forms 3 | from crispy_forms.helper import FormHelper 4 | from crispy_forms.layout import Layout, Div, Submit, HTML, Button, Row, Field, Column 5 | from crispy_forms.bootstrap import AppendedText, PrependedText, PrependedAppendedText, FormActions 6 | from django.utils import timezone 7 | 8 | 9 | class MessageForm(forms.Form): 10 | text_input = forms.CharField() 11 | text_input2 = forms.CharField() 12 | text_input_a = forms.CharField() 13 | text_input_b = forms.CharField() 14 | text_input_c = forms.CharField() 15 | 16 | textarea = forms.CharField( 17 | widget=forms.Textarea(), 18 | ) 19 | 20 | radio_buttons = forms.ChoiceField( 21 | choices=( 22 | ('option_one', 23 | "Option one is this and that be sure to include why it's great"), 24 | ('option_two', 25 | "Option two can is something else and selecting it will deselect option one") 26 | ), 27 | widget=forms.RadioSelect, 28 | initial='option_two', 29 | ) 30 | 31 | checkboxes = forms.MultipleChoiceField( 32 | choices=( 33 | ('option_one', 34 | "Option one is this and that be sure to include why it's great"), 35 | ('option_two', 36 | 'Option two can also be checked and included in form results'), 37 | ('option_three', 38 | 'Option three can yes, you guessed it also be checked and included in form results') 39 | ), 40 | initial='option_one', 41 | widget=forms.CheckboxSelectMultiple, 42 | help_text="Note: Labels surround all the options for much larger click areas and a more usable form.", 43 | ) 44 | 45 | grouped_checkboxes = forms.MultipleChoiceField( 46 | choices=( 47 | ('Group 1', 48 | ((1, "Option one"), 49 | (2, "Option two"), 50 | (3, "Option three"))), 51 | ('Group 2', 52 | ((4, "Option four"), 53 | (5, "Option five"), 54 | (6, "Option six"))), 55 | ), 56 | initial=(1,), 57 | widget=forms.CheckboxSelectMultiple, 58 | ) 59 | 60 | appended_text = forms.CharField( 61 | help_text="Here's more help text" 62 | ) 63 | 64 | appended_text2 = forms.CharField( 65 | help_text="And a bigger appended text field" 66 | ) 67 | 68 | appended_select = forms.ChoiceField( 69 | label="Select field with appended text", 70 | choices=[(1, "Choice 1"), (2, "Choice 2")], 71 | help_text="Some help text" 72 | ) 73 | 74 | prepended_appended_select = forms.ChoiceField( 75 | label="Select field with both preprended and appended text", 76 | choices=[(1, "Choice 1"), (2, "Choice 2")], 77 | help_text="Some help text" 78 | ) 79 | 80 | prepended_select = forms.ChoiceField( 81 | label="Select field with prepended text", 82 | choices=[(1, "Choice 1"), (2, "Choice 2")], 83 | help_text="Some help text" 84 | ) 85 | 86 | prepended_text = forms.CharField() 87 | 88 | prepended_text_two = forms.CharField() 89 | 90 | select = forms.ChoiceField( 91 | choices=(('1', 'North'), ('2', 'South'), ('3', 'East'), ('4', 'West')), 92 | help_text='Direction to go' 93 | ) 94 | 95 | multicolon_select = forms.MultipleChoiceField( 96 | choices=(('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')), 97 | ) 98 | datetime_field = forms.SplitDateTimeField( 99 | initial=timezone.now() 100 | ) 101 | boolean_field = forms.BooleanField() 102 | 103 | # Bootstrap4 104 | helper = FormHelper() 105 | helper.layout = Layout( 106 | Field('text_input'), 107 | Field('text_input2', css_class='input-lg'), 108 | Field('textarea', rows="3"), 109 | 'radio_buttons', 110 | Field('checkboxes', style="background: #FAFAFA"), 111 | AppendedText('appended_text', '.00'), 112 | AppendedText('appended_text2', '.00', css_class='input-lg'), 113 | AppendedText('appended_select', '.00'), 114 | PrependedAppendedText('prepended_appended_select', '$', '.00'), 115 | PrependedText('prepended_select', '$'), 116 | PrependedText('prepended_text', 117 | '', 118 | active=True), 119 | PrependedText('prepended_text_two', '@'), 120 | 'select', 121 | 'multicolon_select', 122 | 'boolean_field', 123 | 'grouped_checkboxes', 124 | 'datetime_field', 125 | Row( 126 | Column('text_input_a', 'text_input_b', css_class="col-xs-6"), 127 | Column('text_input_c', css_class="col-xs-6"), 128 | ), 129 | FormActions( 130 | Submit('save_changes', 'Save changes', css_class="btn-primary"), 131 | Submit('cancel', 'Cancel'), 132 | ) 133 | ) 134 | 135 | helper.label_class = 'col-lg-4' 136 | helper.field_class = 'col-lg-8' 137 | -------------------------------------------------------------------------------- /bootstrap3/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/bootstrap3/migrations/__init__.py -------------------------------------------------------------------------------- /bootstrap3/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /bootstrap3/templates/bootstrap3/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Bootstrap 3 | Crispy Forms Test Project 10 | 11 | 12 | 13 | 15 | 16 | 17 |
18 | {% block content %} 19 | {% endblock %} 20 |
21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /bootstrap3/templates/bootstrap3/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap3/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | {% block content %} 5 | 25 | 26 |

Bootstrap 3

27 | {% crispy form %} 28 | {% crispy form_failing %} 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /bootstrap3/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /bootstrap3/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.conf import settings 3 | from django.shortcuts import render 4 | 5 | 6 | def index(request): 7 | settings.CRISPY_TEMPLATE_PACK = 'bootstrap3' 8 | from bootstrap3.forms import MessageForm 9 | # This view is missing all form handling logic for simplicity of the example 10 | return render(request, 'bootstrap3/index.html', {'form': MessageForm(), 'form_failing': MessageForm(data={})}) 11 | -------------------------------------------------------------------------------- /bootstrap4/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/bootstrap4/__init__.py -------------------------------------------------------------------------------- /bootstrap4/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /bootstrap4/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import datetime 3 | 4 | from django import forms 5 | from django.forms import widgets, modelform_factory 6 | from crispy_forms.helper import FormHelper 7 | from crispy_forms.layout import Layout, Div, Submit, HTML, Button, Row, Field, Column 8 | from crispy_forms.bootstrap import AppendedText, PrependedText, PrependedAppendedText, FormActions, InlineCheckboxes, \ 9 | InlineRadios 10 | from django.utils import timezone 11 | 12 | from bootstrap4 import models 13 | 14 | 15 | class MessageForm(forms.Form): 16 | text_input = forms.CharField( 17 | help_text="help on a text_input", 18 | ) 19 | text_input_a = forms.CharField() 20 | text_input_b = forms.CharField() 21 | text_input_c = forms.CharField() 22 | 23 | textarea = forms.CharField( 24 | widget=forms.Textarea(), 25 | help_text="help on a textarea", 26 | ) 27 | 28 | radio_buttons = forms.ChoiceField( 29 | choices=( 30 | ('option_one', 31 | "Option one is this and that be sure to include why it's great"), 32 | ('option_two', 33 | "Option two can is something else and selecting it will deselect option one") 34 | ), 35 | widget=forms.RadioSelect, 36 | initial='option_two', 37 | help_text="help on a radio_buttons", 38 | ) 39 | 40 | inline_radio_buttons = forms.ChoiceField( 41 | choices=( 42 | ('option_one', 'option_one'), 43 | ('option_two', 'option_two') 44 | ), 45 | widget=forms.RadioSelect, 46 | initial='option_two', 47 | help_text="help on a inline_radio_buttons", 48 | ) 49 | 50 | checkboxes = forms.MultipleChoiceField( 51 | choices=( 52 | ('option_one', 53 | "Option one is this and that be sure to include why it's great"), 54 | ('option_two', 55 | 'Option two can also be checked and included in form results'), 56 | ('option_three', 57 | 'Option three can yes, you guessed it also be checked and included in form results') 58 | ), 59 | initial='option_one', 60 | widget=forms.CheckboxSelectMultiple, 61 | help_text="Note: Labels surround all the options for much larger click areas and a more usable form.", 62 | ) 63 | 64 | inline_checkboxes = forms.MultipleChoiceField( 65 | choices=( 66 | ('bird', 67 | "it's a bird"), 68 | ('plane', 69 | "it's a plane"), 70 | ('dunno', 71 | "it's something else !") 72 | ), 73 | initial='option_one', 74 | widget=forms.CheckboxSelectMultiple, 75 | help_text="help on a inline_checkboxes", 76 | ) 77 | 78 | grouped_checkboxes = forms.MultipleChoiceField( 79 | choices=( 80 | ('Group 1', 81 | ((1, "Option one"), 82 | (2, "Option two"), 83 | (3, "Option three"))), 84 | ('Group 2', 85 | ((4, "Option four"), 86 | (5, "Option five"), 87 | (6, "Option six"))), 88 | ), 89 | initial=(1,), 90 | widget=forms.CheckboxSelectMultiple, 91 | help_text="help on a grouped_checkboxes", 92 | ) 93 | 94 | appended_text = forms.CharField( 95 | help_text="Here's more help text" 96 | ) 97 | 98 | appended_text2 = forms.CharField( 99 | help_text="And a bigger appended text field" 100 | ) 101 | 102 | appended_select = forms.ChoiceField( 103 | label="Select field with appended text", 104 | choices=[(1, "Choice 1"), (2, "Choice 2")], 105 | help_text="Some help text" 106 | ) 107 | 108 | prepended_appended_select = forms.ChoiceField( 109 | label="Select field with both preprended and appended text", 110 | choices=[(1, "Choice 1"), (2, "Choice 2")], 111 | help_text="Some help text" 112 | ) 113 | 114 | prepended_select = forms.ChoiceField( 115 | label="Select field with prepended text", 116 | choices=[(1, "Choice 1"), (2, "Choice 2")], 117 | help_text="Some help text" 118 | ) 119 | 120 | prepended_text = forms.CharField() 121 | 122 | prepended_text_two = forms.CharField() 123 | 124 | select = forms.ChoiceField( 125 | choices=(('1', 'North'), ('2', 'South'), ('3', 'East'), ('4', 'West')), 126 | help_text='Direction to go' 127 | ) 128 | 129 | multicolon_select = forms.MultipleChoiceField( 130 | choices=(('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')), 131 | help_text=( 132 | 'This strange option climbing out of the box is in the examples too ' 133 | 'Only without Flexbox ' 134 | 'https://v4-alpha.getbootstrap.com/components/forms/#form-controls'), 135 | ) 136 | 137 | datetime_field = forms.SplitDateTimeField( 138 | initial=timezone.now() 139 | ) 140 | boolean_field = forms.BooleanField() 141 | 142 | file_field = forms.FileField( 143 | label="file_field", 144 | widget=widgets.FileInput(), 145 | help_text='with widgets.FileInput()' 146 | ) 147 | 148 | file_field_raw = forms.FileField( 149 | label="file_field_raw", 150 | help_text='with default widget' 151 | ) 152 | 153 | # Bootstrap4 154 | helper = FormHelper() 155 | helper.layout = Layout( 156 | Field('text_input', css_class='form-control-lg'), 157 | Field('textarea', rows="3", css_class='form-control-lg'), 158 | 'radio_buttons', 159 | InlineRadios('inline_radio_buttons'), 160 | Field('checkboxes', style="background: #FAFAFA"), 161 | InlineCheckboxes('inline_checkboxes'), 162 | AppendedText('appended_text', '.00'), 163 | AppendedText('appended_text2', '.00', css_class='form-control-lg'), 164 | AppendedText('appended_select', '.00'), 165 | PrependedAppendedText('prepended_appended_select', '$', '.00'), 166 | PrependedText('prepended_select', '$'), 167 | PrependedText('prepended_text', 168 | '', 169 | active=True), 170 | PrependedText('prepended_text_two', '@'), 171 | 'select', 172 | 'multicolon_select', 173 | 'boolean_field', 174 | 'file_field', 175 | 'file_field_raw', 176 | 'grouped_checkboxes', 177 | Row( 178 | Column('text_input_a','text_input_b'), 179 | Column('text_input_c'), 180 | ), 181 | 'datetime_field', 182 | FormActions( 183 | Submit('save_changes', 'Save changes', css_class="btn-primary"), 184 | Submit('cancel', 'Cancel'), 185 | ) 186 | ) 187 | helper.use_custom_control = True 188 | 189 | class HorizontalMessageForm(forms.Form): 190 | text_input = forms.CharField() 191 | text_input_a = forms.CharField() 192 | text_input_b = forms.CharField() 193 | text_input_c = forms.CharField() 194 | 195 | textarea = forms.CharField( 196 | widget=forms.Textarea(), 197 | ) 198 | 199 | radio_buttons = forms.ChoiceField( 200 | choices=( 201 | ('option_one', 202 | "Option one is this and that be sure to include why it's great"), 203 | ('option_two', 204 | "Option two can is something else and selecting it will deselect option one") 205 | ), 206 | widget=forms.RadioSelect, 207 | initial='option_two', 208 | help_text="help on a radio_buttons", 209 | ) 210 | 211 | inline_radio_buttons = forms.ChoiceField( 212 | choices=( 213 | ('option_one', 'option_one'), 214 | ('option_two', 'option_two') 215 | ), 216 | widget=forms.RadioSelect, 217 | initial='option_two', 218 | help_text="help on a inline_radio_buttons", 219 | ) 220 | 221 | checkboxes = forms.MultipleChoiceField( 222 | choices=( 223 | ('option_one', 224 | "Option one is this and that be sure to include why it's great"), 225 | ('option_two', 226 | 'Option two can also be checked and included in form results'), 227 | ('option_three', 228 | 'Option three can yes, you guessed it also be checked and included in form results') 229 | ), 230 | initial='option_one', 231 | widget=forms.CheckboxSelectMultiple, 232 | help_text="Note: Labels surround all the options for much larger click areas and a more usable form.", 233 | ) 234 | 235 | inline_checkboxes = forms.MultipleChoiceField( 236 | choices=( 237 | ('bird', 238 | "it's a bird"), 239 | ('plane', 240 | "it's a plane"), 241 | ('dunno', 242 | "it's something else !") 243 | ), 244 | initial='option_one', 245 | widget=forms.CheckboxSelectMultiple, 246 | help_text="help on a inline_checkboxes", 247 | ) 248 | 249 | appended_text = forms.CharField( 250 | help_text="Here's more help text" 251 | ) 252 | 253 | appended_text2 = forms.CharField( 254 | help_text="And a bigger appended text field" 255 | ) 256 | 257 | prepended_text = forms.CharField() 258 | 259 | prepended_text_two = forms.CharField() 260 | 261 | select = forms.ChoiceField( 262 | choices=(('1', 'North'), ('2', 'South'), ('3', 'East'), ('4', 'West')), 263 | help_text='Direction to go' 264 | ) 265 | 266 | multicolon_select = forms.MultipleChoiceField( 267 | choices=(('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')), 268 | help_text=( 269 | 'This strange option climbing out of the box is in the examples too ' 270 | 'Only without Flexbox ' 271 | 'https://v4-alpha.getbootstrap.com/components/forms/#form-controls'), 272 | ) 273 | 274 | boolean_field = forms.BooleanField() 275 | file_field = forms.FileField( 276 | widget=widgets.FileInput(), 277 | help_text='with FileInput widget', 278 | required=True, 279 | ) 280 | 281 | file_field_raw = forms.FileField( 282 | help_text='with default widget', 283 | required=True, 284 | ) 285 | 286 | 287 | # Bootstrap4 288 | helper = FormHelper() 289 | helper.layout = Layout( 290 | Field('text_input', css_class='form-control-lg'), 291 | Field('textarea', rows="3", css_class='form-control-lg'), 292 | Field('radio_buttons'), 293 | InlineRadios('inline_radio_buttons'), 294 | Field('checkboxes', style="background: #FAFAFA"), 295 | InlineCheckboxes('inline_checkboxes'), 296 | AppendedText('appended_text', '.00'), 297 | AppendedText('appended_text2', '.00', css_class='form-control-lg'), 298 | PrependedText('prepended_text', 299 | '', 300 | active=True), 301 | PrependedText('prepended_text_two', '@'), 302 | Field('select'), 303 | Field('multicolon_select'), 304 | Field('boolean_field'), 305 | Field('file_field'), 306 | Field('file_field_raw'), 307 | FormActions( 308 | Submit('save_changes', 'Save changes', css_class="btn-primary"), 309 | Submit('cancel', 'Cancel'), 310 | ), 311 | Row( 312 | Column('text_input_a','text_input_b'), 313 | Column('text_input_c'), 314 | ), 315 | ) 316 | helper.form_class = 'form-horizontal' 317 | 318 | helper.use_custom_control = False 319 | helper.label_class = 'col-4' 320 | helper.field_class = 'col-8' 321 | 322 | FormWithFileField = modelform_factory(models.WithFileField, fields="__all__") 323 | 324 | class HorizontalModelForm(forms.ModelForm): 325 | class Meta: 326 | model = models.WithFileField 327 | fields = '__all__' 328 | helper = FormHelper() 329 | helper.label_class = 'col-4' 330 | helper.field_class = 'col-8' 331 | helper.form_class = 'form-horizontal' -------------------------------------------------------------------------------- /bootstrap4/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/bootstrap4/migrations/__init__.py -------------------------------------------------------------------------------- /bootstrap4/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class WithFileField(models.Model): 5 | my_file = models.FileField(null=True, blank=True, help_text="help") 6 | my_char = models.CharField(null=True, blank=True, help_text="help", max_length=32) 7 | -------------------------------------------------------------------------------- /bootstrap4/templates/bootstrap4/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bootstrap 4 | Crispy Forms Test Project 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | {% block content %} 16 | {% endblock %} 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /bootstrap4/templates/bootstrap4/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap4/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | {% block content %} 5 | 22 | 23 |

Bootstrap 4

24 |
25 |
26 | {% csrf_token %} 27 |
28 |

Default form

29 | {% crispy default_form %} 30 |
31 |
32 |

Default form with failing validation #

33 | {% crispy default_form_failing %} 34 |
35 |
36 |

Model form #

37 | {% crispy model_form %} 38 |
39 |
40 |

Horizontal Model form #

41 | {% crispy horizontal_model_form %} 42 |
43 |
44 |

Horizontal form #

45 | {% crispy horizontal_form %} 46 |
47 |
48 |

Horizontal form with failing validation #

49 | {% crispy horizontal_form_failing %} 50 |
51 |
52 |
53 | {% endblock %} 54 | -------------------------------------------------------------------------------- /bootstrap4/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /bootstrap4/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | 4 | import errno 5 | from django.conf import settings 6 | from django.shortcuts import render 7 | 8 | from bootstrap4.forms import FormWithFileField, HorizontalModelForm 9 | from bootstrap4.models import WithFileField 10 | 11 | 12 | def index(request): 13 | settings.CRISPY_TEMPLATE_PACK = 'bootstrap4' 14 | from bootstrap4.forms import HorizontalMessageForm, MessageForm 15 | 16 | filename = '.' + ("/somedire" * 10) 17 | try: 18 | os.makedirs(filename) 19 | except FileExistsError as e: 20 | assert e.errno is errno.EEXIST 21 | filename += "/" + ("myfile-" * 10) + ".txt" 22 | with open(filename, "w") as f: 23 | f.write('Hello world') 24 | instance = WithFileField(my_file=filename) 25 | 26 | # This view is missing all form handling logic for simplicity of the example 27 | return render(request, 'bootstrap4/index.html', 28 | { 29 | 'model_form': FormWithFileField( 30 | instance=instance, 31 | prefix='model_form', 32 | ), 33 | 'horizontal_model_form': HorizontalModelForm( 34 | instance=instance, 35 | prefix='horizontal_model_form', 36 | ), 37 | 'default_form': MessageForm( 38 | data=request.POST if request.method == "POST" else None, 39 | prefix='default_form', 40 | ), 41 | 'horizontal_form': HorizontalMessageForm( 42 | data=request.POST if request.method == "POST" else None, 43 | prefix='horizontal_form', 44 | ), 45 | 'default_form_failing': MessageForm( 46 | data={}, 47 | prefix='default_form_failing', 48 | ), 49 | 'horizontal_form_failing': HorizontalMessageForm( 50 | data={}, 51 | prefix='horizontal_form_failing', 52 | ), 53 | }) 54 | -------------------------------------------------------------------------------- /django_rendering/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/django_rendering/__init__.py -------------------------------------------------------------------------------- /django_rendering/templates/django_rendering/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'bootstrap4/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | {% block content %} 5 | 22 | 23 |

Bootstrap 4

24 |
25 |
26 | {% csrf_token %} 27 |
28 |

Default form

29 | {{ default_form.as_p }} 30 |
31 |
32 |

Default form with failing validation

33 | {{ default_form_failing.as_p }} 34 |
35 |
36 |
37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /django_rendering/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.conf import settings 3 | from django.shortcuts import render 4 | 5 | 6 | def index(request): 7 | from bootstrap4.forms import HorizontalMessageForm, MessageForm 8 | 9 | # This view is missing all form handling logic for simplicity of the example 10 | return render(request, 'django_rendering/index.html', 11 | { 12 | 'default_form': MessageForm( 13 | data=request.POST if request.method == "POST" else None, 14 | prefix='default_form', 15 | ), 16 | 'horizontal_form': HorizontalMessageForm( 17 | data=request.POST if request.method == "POST" else None, 18 | prefix='horizontal_form', 19 | ), 20 | 'default_form_failing': MessageForm( 21 | data={}, 22 | prefix='default_form_failing', 23 | ), 24 | 'horizontal_form_failing': HorizontalMessageForm( 25 | data={}, 26 | prefix='horizontal_form_failing', 27 | ), 28 | }) 29 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | crispy-forms-semantic-ui>=0.2.0 # added to ease up testing of semantic ui templates 2 | django-crispy-forms>=2.0 # Use pip install -e ../django-crispy-forms for local dev 3 | crispy-bootstrap3>=2024.1 4 | crispy-bootstrap4>=2024.1 5 | Django>=4.2 6 | gunicorn>=20.0.4 7 | pytz>=2019.3 8 | -------------------------------------------------------------------------------- /semantic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/semantic/__init__.py -------------------------------------------------------------------------------- /semantic/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /semantic/forms.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django import forms 3 | from crispy_forms.helper import FormHelper 4 | from crispy_forms.layout import Layout, Div, Submit, HTML, Button, Row, Field, Column 5 | from crispy_forms.bootstrap import AppendedText, PrependedText, FormActions 6 | 7 | 8 | class MessageForm(forms.Form): 9 | text_input = forms.CharField() 10 | text_input_a = forms.CharField() 11 | text_input_b = forms.CharField() 12 | text_input_c = forms.CharField() 13 | 14 | textarea = forms.CharField( 15 | widget=forms.Textarea(), 16 | ) 17 | 18 | radio_buttons = forms.ChoiceField( 19 | choices=( 20 | ('option_one', 21 | "Option one is this and that be sure to include why it's great"), 22 | ('option_two', 23 | "Option two can is something else and selecting it will deselect option one") 24 | ), 25 | widget=forms.RadioSelect, 26 | initial='option_two', 27 | ) 28 | 29 | checkboxes = forms.MultipleChoiceField( 30 | choices=( 31 | ('option_one', 32 | "Option one is this and that be sure to include why it's great"), 33 | ('option_two', 34 | 'Option two can also be checked and included in form results'), 35 | ('option_three', 36 | 'Option three can yes, you guessed it also be checked and included in form results') 37 | ), 38 | initial='option_one', 39 | widget=forms.CheckboxSelectMultiple, 40 | help_text="Note: Labels surround all the options for much larger click areas and a more usable form.", 41 | ) 42 | 43 | grouped_checkboxes = forms.MultipleChoiceField( 44 | choices=( 45 | ('Group 1', 46 | ((1, "Option one"), 47 | (2, "Option two"), 48 | (3, "Option three"))), 49 | ('Group 2', 50 | ((4, "Option four"), 51 | (5, "Option five"), 52 | (6, "Option six"))), 53 | ), 54 | initial=(1,), 55 | widget=forms.CheckboxSelectMultiple, 56 | ) 57 | 58 | multicolon_select = forms.MultipleChoiceField( 59 | choices=(('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')), 60 | ) 61 | 62 | # Bootstrap4 63 | helper = FormHelper() 64 | helper.layout = Layout( 65 | Field('text_input'), 66 | Field('textarea'), 67 | 'radio_buttons', 68 | Field('checkboxes', style="background: #FAFAFA"), 69 | Row( 70 | Column('text_input_a','text_input_b'), 71 | Column('text_input_c'), 72 | ), 73 | FormActions( 74 | Submit('save_changes', 'Save changes', css_class="btn-primary"), 75 | Submit('cancel', 'Cancel'), 76 | ) 77 | ) 78 | 79 | class HorizontalMessageForm(forms.Form): 80 | text_input = forms.CharField() 81 | text_input_a = forms.CharField() 82 | text_input_b = forms.CharField() 83 | text_input_c = forms.CharField() 84 | 85 | textarea = forms.CharField( 86 | widget=forms.Textarea(), 87 | ) 88 | 89 | radio_buttons = forms.ChoiceField( 90 | choices=( 91 | ('option_one', 92 | "Option one is this and that be sure to include why it's great"), 93 | ('option_two', 94 | "Option two can is something else and selecting it will deselect option one") 95 | ), 96 | widget=forms.RadioSelect, 97 | initial='option_two', 98 | ) 99 | 100 | checkboxes = forms.MultipleChoiceField( 101 | choices=( 102 | ('option_one', 103 | "Option one is this and that be sure to include why it's great"), 104 | ('option_two', 105 | 'Option two can also be checked and included in form results'), 106 | ('option_three', 107 | 'Option three can yes, you guessed it also be checked and included in form results') 108 | ), 109 | initial='option_one', 110 | widget=forms.CheckboxSelectMultiple, 111 | help_text="Note: Labels surround all the options for much larger click areas and a more usable form.", 112 | ) 113 | 114 | appended_text = forms.CharField( 115 | help_text="Here's more help text" 116 | ) 117 | 118 | appended_text2 = forms.CharField( 119 | help_text="And a bigger appended text field" 120 | ) 121 | 122 | prepended_text = forms.CharField() 123 | 124 | prepended_text_two = forms.CharField() 125 | 126 | select = forms.ChoiceField( 127 | choices=(('1', 'North'), ('2', 'South'), ('3', 'East'), ('4', 'West')), 128 | help_text='Direction to go' 129 | ) 130 | 131 | multicolon_select = forms.MultipleChoiceField( 132 | choices=(('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5')), 133 | ) 134 | 135 | # Bootstrap4 136 | helper = FormHelper() 137 | helper.layout = Layout( 138 | Field('text_input'), 139 | Field('textarea', rows="6"), 140 | 'radio_buttons', 141 | Field('checkboxes'), 142 | AppendedText('appended_text', '.00'), 143 | AppendedText('appended_text2', '.00', css_class='form-control-lg'), 144 | PrependedText('prepended_text', 145 | '', 146 | active=True), 147 | PrependedText('prepended_text_two', '@'), 148 | 'select', 149 | 'multicolon_select', 150 | Row( 151 | Column('text_input_a','text_input_b'), 152 | Column('text_input_c'), 153 | ), 154 | FormActions( 155 | Submit('save_changes', 'Save changes', css_class="btn-primary"), 156 | Submit('cancel', 'Cancel'), 157 | ) 158 | ) 159 | 160 | helper.label_class = '' 161 | helper.field_class = 'six wide field' 162 | -------------------------------------------------------------------------------- /semantic/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/semantic/migrations/__init__.py -------------------------------------------------------------------------------- /semantic/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /semantic/templates/semantic/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | {% block content %} 15 | {% endblock %} 16 |
17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /semantic/templates/semantic/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'semantic/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | {% block content %} 5 |
6 | 12 |
13 | 14 |
15 |

Semantic UI layouts

16 |
17 |
18 | 19 |

20 | 21 |
22 | Default 23 |
24 |

25 | 26 |
27 | {% crispy default_form %} 28 |
29 | 30 |
31 |
32 | 33 |

34 | 35 |
36 | Default 37 |
38 |

39 | 40 |
41 | {% crispy default_form_failing %} 42 |
43 | 44 |
45 |
46 | 47 |

48 | 49 |
50 | Horizontal form 51 |
52 |

53 | 54 |
55 | {% crispy horizontal_form %} 56 |
57 | 58 |
59 |
60 | 61 |

62 | 63 |
64 | Horizontal form 65 |
66 |

67 | 68 |
69 | {% crispy horizontal_form_failing %} 70 |
71 | 72 |
73 |
74 |
75 | {% endblock %} 76 | -------------------------------------------------------------------------------- /semantic/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /semantic/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from django.shortcuts import render 3 | 4 | 5 | def index(request): 6 | #settings.CRISPY_TEMPLATE_PACK = 'semantic_ui' 7 | from semantic.forms import HorizontalMessageForm, MessageForm 8 | 9 | # This view is missing all form handling logic for simplicity of the example 10 | return render(request, 'semantic/index.html', 11 | { 12 | 'default_form': MessageForm(), 13 | 'horizontal_form': HorizontalMessageForm(), 14 | 'default_form_failing': MessageForm(data={}), 15 | 'horizontal_form_failing': HorizontalMessageForm(data={}), 16 | }) 17 | -------------------------------------------------------------------------------- /test_project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/django-crispy-forms/crispy-test-project/7a8a5efc5d50bf7e3e6c55f38468cbbb6e7faffa/test_project/__init__.py -------------------------------------------------------------------------------- /test_project/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for test_project project. 3 | 4 | Generated by 'django-admin startproject' using Django 1.8.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/1.8/ref/settings/ 11 | """ 12 | 13 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 14 | import os 15 | 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'TOTALLY A SAFE SECRET_KEY' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [ 29 | u'crispy-test-project.herokuapp.com', 30 | u'127.0.0.1' 31 | ] 32 | 33 | 34 | # Application definition 35 | 36 | INSTALLED_APPS = ( 37 | 'django.contrib.admin', 38 | 'django.contrib.auth', 39 | 'django.contrib.contenttypes', 40 | 'django.contrib.sessions', 41 | 'django.contrib.messages', 42 | 'django.contrib.staticfiles', 43 | # dependencies 44 | 'crispy_forms', 45 | # template packs 46 | 'crispy_forms_semantic_ui', 47 | 'crispy_bootstrap3', 48 | 'crispy_bootstrap4', 49 | # internal apps 50 | 'bootstrap3', 51 | 'bootstrap4', 52 | 'semantic', 53 | 'django_rendering', 54 | ) 55 | 56 | MIDDLEWARE = ( 57 | 'django.contrib.sessions.middleware.SessionMiddleware', 58 | 'django.middleware.common.CommonMiddleware', 59 | 'django.middleware.csrf.CsrfViewMiddleware', 60 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 61 | 'django.contrib.messages.middleware.MessageMiddleware', 62 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 63 | 'django.middleware.security.SecurityMiddleware', 64 | ) 65 | 66 | ROOT_URLCONF = 'test_project.urls' 67 | 68 | TEMPLATES = [ 69 | { 70 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 71 | 'DIRS': [], 72 | 'APP_DIRS': True, 73 | 'OPTIONS': { 74 | 'context_processors': [ 75 | 'django.template.context_processors.debug', 76 | 'django.template.context_processors.request', 77 | 'django.contrib.auth.context_processors.auth', 78 | 'django.contrib.messages.context_processors.messages', 79 | ], 80 | }, 81 | }, 82 | ] 83 | 84 | CRISPY_ALLOWED_TEMPLATE_PACKS = ('bootstrap3', 'bootstrap4', 'semantic-ui',) 85 | 86 | WSGI_APPLICATION = 'test_project.wsgi.application' 87 | 88 | 89 | # Database 90 | # https://docs.djangoproject.com/en/1.8/ref/settings/#databases 91 | 92 | DATABASES = { 93 | 'default': { 94 | 'ENGINE': 'django.db.backends.sqlite3', 95 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 96 | } 97 | } 98 | 99 | 100 | # Internationalization 101 | # https://docs.djangoproject.com/en/1.8/topics/i18n/ 102 | 103 | LANGUAGE_CODE = 'en-us' 104 | 105 | TIME_ZONE = 'UTC' 106 | 107 | USE_I18N = True 108 | 109 | USE_L10N = True 110 | 111 | USE_TZ = True 112 | 113 | 114 | # Static files (CSS, JavaScript, Images) 115 | # https://docs.djangoproject.com/en/1.8/howto/static-files/ 116 | 117 | STATIC_URL = '/static/' 118 | -------------------------------------------------------------------------------- /test_project/urls.py: -------------------------------------------------------------------------------- 1 | """test_project URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/1.8/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Add an import: from blog import urls as blog_urls 14 | 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) 15 | """ 16 | from django.urls import path 17 | 18 | from bootstrap3.views import index as bootstrap_3_preview 19 | from bootstrap4.views import index as bootstrap_4_preview 20 | from semantic.views import index as semantic_preview 21 | from django_rendering.views import index as django_rendering_preview 22 | 23 | urlpatterns = [ 24 | path('', bootstrap_4_preview), 25 | path('django', django_rendering_preview, name='django_rendering.views.index'), 26 | path('bootstrap3', bootstrap_3_preview, name='bootstrap3.views.index'), 27 | path('bootstrap4', bootstrap_4_preview, name='bootstrap4.views.index'), 28 | path('semantic', semantic_preview, name='semantic.views.index'), 29 | ] 30 | -------------------------------------------------------------------------------- /test_project/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for test_project project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings") 15 | 16 | application = get_wsgi_application() 17 | --------------------------------------------------------------------------------