consider this model on Django:
class My_model(models.Model):
my_choices = { '1:first' 2:second'}
myfield1=CharField()
myfield2=CharField(choices=my_choices)
Then on my form:
class My_form(forms.ModelForm):
class Meta:
model = My_model
fields = ['myfield1', 'myfield2']
My views:
def get_name(request):
if request.method == 'POST':
form = My_form(request.POST)
if form.is_valid():
return HttpResponseRedirect('/')
else:
form = My_form()
return render(request, 'form/myform.html', {'form': form})
On my template:
{% extends "base.html" %}
{% block content %}
<form action="/tlevels/" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}
On my base.html, I will load this template like this:
{% extends "base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="p-3 mb-2 bg-info text-white" style="margin-left:20px; margin-bottom:20px;">Status</div>
<div class="form-row" style="margin-left:20px; margin-bottom:20px; margin-top:20px;">
<div class="form-group col-md-6 mb-0">
{{ form.myfield1|as_crispy_field }}
</div>
<div class="form-group col-md-6 mb-0">
{{ form.myfield2|as_crispy_field }}
</div>
</div>
<input type="submit" class="btn btn-primary" value="Submit" style="margin-left:20px;">
</form>
{% endblock %}
What I want, is to have 2 other different templates, with whatever difference on them, and load them depending on the choice made on the ChoiceField, I guess that one way could be on the view, by adding some kind of conditional, and load a different template (html file).
Any ideas?
It is possible to use {% include %} with a variable.
def some_view_after_post(request):
# ... lookup value of myfield2 ...
return render(request, "path/to/after_post.html", {'myfield2: myfield2})
The in the after_post.html template:
<!-- include a template based on user's choice -->
<div class="user-choice">
{% include myfield2 %}
</div>
You'll want to make sure there is no possible way the user can inject an erroneous choice. For example, make sure the value of myfield2 choice is valid before adding it to the context.
Related
I am using Django 4.0.3 with a bootstrap webinterface.
For layout reasons I want my fields in a ModelForm to be grouped and I'm doing it with:
class UserForm(ModelForm):
template_name = "container/form.html"
field_groups = [["email", "company"], ["last_name", "first_name"]]
grouped_fields = []
class Meta:
model = MyUser
fields = ["email", "company", "first_name", "last_name"]
__init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)
def group_fields(self):
for group in self._field_groups:
group_entry = []
for entry in group:
group_entry.append(self.fields[entry])
self.grouped_fields.append(group_entry)
in the view I initialize my form and the regroup the fields:
def user_form(request):
form = UserForm()
form.group_fields()
render(request, "page.html, {"form", form})
The page.html looks like this:
<body>
<div id="form-wrapper">
{{ form }}
</div>
</body>
and the form.html looks like this:
<form action="" method="POST">{% csrf_token %}
{% for field_group in form.grouped_fields %}
<div class="row">
{% for field in field_group %}
<div class="col">
<label>{{ field.label }}</label> {{ field }}
</div>
{% endfor %}
</div>
{% endfor %}
However the rendered fields are displayed as string representations of the field objects:
Email <django.forms.fields.EmailField object at 0x7f98c00e03a0>
Company <django.forms.fields.CharField object at 0x7f98c00e0250>
Last name <django.forms.fields.CharField object at 0x7f98c00e0790>
First name <django.forms.fields.CharField object at 0x7f98c00e10c0>
Whereas a common call renders as expected a form with input fields, but not with the desired layout.
{% for field in form %}
<div class="row">
<div class="col">
{{ field.label_tag }} {{ field }}
</div>
</div>
{% endfor %}
I also tried to move the call of the group_fields method to the form init but had no success.
Is there a way to render the fields, that are stored in my grouped_fields container correctly?
After quiet a time of trying this and that I ended up writing a wrapper for ModelForm, define my field_groups there and rendered it in the template.
It is not nice, but it does the trick.
<form action="" method="post">
{% for fieldgroup in form.field_groups %}
<div class="row fieldgroup">
{% for fieldname in fieldgroup %}
{% for field in form %}
{% if field.name == fieldname %}
<div class="col pt-2">
<label class="form-label">{{ field.label }}</label>
{{ field }}
</div>
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
<button type="submit">Submit</button>
</form>
I'm trying to get the users input and add to a table in the database, everything goes smoothly with no errors .. but the input is not added to DB
urls.py
path('category/add/', views.add_cat, name="add_cat"),
view.py
def add_cat(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CatForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
entry = Categories.objects.create(category_name=new_cat_name)
entry.save()
# ...
# redirect to a new URL:
return HttpResponseRedirect('/')
# if a GET (or any other method) we'll create a blank form
else:
form = CatForm()
return render(request, 'add_cat.html', {'form': form})
add_cat.html
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="/" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
{% load static %}
<form action="" method="post">
{% csrf_token %}
{% for form in form %}
<h3 align="center">{{ form.label }}</h3>
<div align="center">{{ form }}</div>
<br>
<br>
{% endfor %}
<div align="center">
<input type="submit" class="btn btn-dark" style="width: 100px;"value="إضافة" />
</div>
</form>
{% endblock %}
change your form action, you were posting the data to '/' url but you need to put it in your add view
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
Im trying to create a form where the user selects from a gallery of images and it saves it to the database. The code below currently renders some radio buttons in the html output. Is there anyway I can change these to images i have saved in a static directory so the user can click on images instead? Would be great if I could change what it saves in the database to what I needed instead of image urls as well. Theres lots of documentation on uploading images but not much I could find on selecting images. Im using django 1.9.7 and python 3.5
models.py
client_choices = (('client1', 'Client 1'),
('client2', 'Client 2'),
('client3', 'Client 3'),
('client4', 'Client 4'),
('client5', 'Client 5'))
class ClientSelect(models.Model):
client = MultiSelectField(choices=client_choices)
forms.py
from app.models import ClientSelect
class ClientSelectForm(forms.ModelForm):
class Meta:
model = ClientSelect
fields = '__all__'
views.py
class FormWizard(SessionWizardView):
template_name = "app/clientchoices.html"
#define what the wizard does when its finished collecting information
def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)
return render_to_response('app/about.html', {'form_data': form_data})
urls.py
url(r'^clientchoices$', FormWizard.as_view([ClientSelectForm]) , name='clientchoices'),
clientchoices.html
{% load staticfiles %}
{% block content %}
<section class="content">
<div class="container">
<div class="fit-form-wrapper">
<h2>Client Choices</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="{% url 'clientchoices' %}" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"First Step"</button>
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"Previous Step"</button>
{% endif %}
<input class="btn btn-brand" type="submit" value="Submit" />
</form>
</div>
</div>
</section>
{% endblock %}
Any help is appreciated thank you
I am trying to create a form in Django with the form wizard where there are multiple (repeating) formsets in the same step of the wizard.
What I have is:
# forms.py
class FormStep1A(forms.Form):
answerA = forms.CharField(max_length=100)
remarkA = forms.CharField(widget=forms.Textarea)
class FormStep1B(forms.Form):
answerB = forms.CharField(max_length=100)
remarkB = forms.CharField(widget=forms.Textarea)
class FormStep1(forms.Form):
partA = formset_factory(FormStep1A)
partB = formset_factory(FormStep1B)
and
# urls.py
STEPS = (
('1', FormStep1),
# ...
)
# FormWizard is a subclass of NamedUrlSessionWizardView
wizard = FormWizard.as_view(STEPS, url_name='form_new_step')
urlpatterns = patterns(
'',
url(r'^new/(?P<step>.+)/$', wizard,
name='form_new_step'),
url(r'^new/$', wizard, name='form_new'),
)
And my template looks the same as in the documentation. However, my form is rendered empty with no fields at all.
I know there are similar questions or recipes out there:
Django formwizard with formsets and forms on same page
django wizard, using form and formset in the same step
Combining a Form and a FormSet in Django: How to pass them in the context?
But I just cannot get this to work. Any help is much appreciated, thank you!
UPDATE: My template looks like this:
{% extends 'base.html' %}
{% load i18n %}
{% block head %}
{{ wizard.form.media }}
{% endblock %}
{% block content %}
<div class="row">
<div class="large-12 columns">
<h3>{% trans "Questionnaire" %}</h3>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
<form action="" method="post">
{% csrf_token %}
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
{% if wizard.steps.prev %}
<button class="button tiny" name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">{% trans "First step" %}</button>
<button class="button tiny" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">{% trans "Prev step" %}</button>
{% endif %}
<input class="button tiny" type="submit" value="{% trans "Submit" %}"/>
</form>
</div>
</div>
{% endblock %}
Django 1.3 documentation on class based views is seeming like a treasure hunt. How to write the class is clear enough... but what kind of template code matches each generic class? Would someone provide a complete example soup to nuts? Here's what I have so far:
urls.py
(r'^brand_create2$', BrandCreate.as_view()),
views.py
from django.views.generic import CreateView
#login_required
class BrandCreate(CreateView):
template_name = 'generic_form_popup.html'
context_object_name = "brand_thingie"
#queryset = models.Brand.objects.all()
success_url = '/'
generic_form_popup.html
????
In this case I'm exploring if it is worth learning the new style, given the older style still works:
urls.py
url(r'^brand_create1$', 'coat.views.brand_create'),
views.py
class formBrand(forms.ModelForm):
class Meta:
model = models.Brand
exclude = ('')
#login_required
def brand_create(request):
form = formBrand
if request.method == 'POST':
form = formBrand(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
passed = dict(
form=form,
MEDIA_URL = settings.MEDIA_URL,
STATIC_URL = settings.STATIC_URL)
return render_to_response('generic_form_popup.html',
passed, context_instance=RequestContext(request))
generic_form_popup.html
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="{{ action }}" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
CreateView inherits from ModelFormMixin, which in turn inherits from FormMixin and SingleObjectMixin.
SingleObjectMixin provides the object template context variable, which is probably not going to be any use in the case of CreateView:
object: The object that this view is displaying. If context_object_name is specified, that variable will also be set in the context, with the same value as object.
But FormMixin provides the form context variable:
form: The form instance that was generated for the view.
Thus, you can refer to the documentation to display a form with a template:
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Which means that the very template you posted should almost work with the class based view:
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
I removed {{ action }} because it is not part of the context, neither in the old-style view, neither with the class based view, so it doesn't make any sense. You should know that if action="" then the browser will submit to the current url. You can force the action to the current url with action="{{ request.path }}" or you can specify another url with the url template tag.
Suppose apply the best practice of naming url patterns, by changing:
(r'^brand_create2$', BrandCreate.as_view()),
to:
(r'^brand_create2$', BrandCreate.as_view(), name='band_create'),
Then you can use: action="{% url band_create %}".
You can also customize further:
<form action="/contact/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
Of course, the fields available in the form depend on your Model.