Hello everyone I have an HTML form as follows:
and after clicking on post i am redirecting it to views.py. can any one tell me how to get the field values of all the fields of the form into views.py.
here's the output
i want the field value in key value pair like shown in above pic i.e. API=hello&Area=hello1 so on...
i know we can do that using this
if html:
<div class="form-group col-md-2">
<label for="param">TAF Parameter</label>
<input type="text" name="inputdata_API" class="form-control" id="inputapi_param" value="API" readonly>
</div>
and view:
def register(request):
api = request.GET.get['inputdata_API']
But in that case i have to write each and every input name in my view
To get form input without individual access, Django provide ModelForm
For resume :
Define a model to store your form informations
class MyModel(models.Model):
api = models.CharField()
# ...
Define a model form linked to the previous model
from django import forms
class MyModelForm(forms.Form):
class Meta:
model = MyModel
fields = ['api', # all others fields you want to display]
In the views.py
from django.http import JsonResponse
from django.shortcuts import redirect
def register(request):
if request.method == 'POST':
# Instanciate the form with posted data
form = MyModelFor(request.POST)
# Check if form is valid
if form.is_valid:
# Create a new MyModel object if the form is valid
form.save() # This is the most benefit line, save you from request.POST['field_name']
# You can eventually return to the same page
return redirect('.')
else: # The form is invalid return a json response
return JsonResponse({"Error": "Form is invalid"}, status=400)
At the end render the form fields in the template like this :
<form action="{% url 'url_to_register' %}" method="post" novalidate>
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Register</button>
</form>
But the downside of this approach is the style of the form on the frontend :
You need to add some Bootstrap class for example in the right place to make it nice to look, it is a a counterpart...
Django form documentation.
Related
In my Django project, I want to have the institution selection selected from a list, for this I created a model for the institution name and I want the user to enter it as a pop-up window or a list selection for this:
models.py
class Institution(models.Model):
institutionName = models.CharField(max_length=200,null=True,blank=True)
def __str__(self):
return self.institutionName
views.py
def getInstitutionName(request):
context = {'institutionName':Institution.objects.all()}
return HttpResponse(context)
I created it in the form of html, but I'm having trouble with how to integrate the data I bring here with html. In this process, I want to make a form that includes other entries, only the institution entry in this way. My question on this subject is, what action should I take while printing the data I have brought here to the screen.
Django provides the form field ModelChoiceField. When this field of a form is rendered, it will by default generate a <select> with <option> for each instance in a queryset.
You can either transform this using Javascript, or you can write (or look for) your own widget to use with this field, to generate the HTML you desire.
I'd start by writing a view with such a form and no fancy stuff. When you have it working, then start developing it into the pop-up you seek.
class InstitutionSelectForm ( forms.Form):
institution = forms.ModelChoiceField(
queryset = Institution.objects.all(),
)
# other fields
class InstitutionSelectView( FormView):
form_class = InstitutionSelectView
template_name = 'myapp/institution_select.html'
def form_valid( self, form):
institution_instance = form.cleaned_data['institution']
# do whatever is called for with this institution and
# any other form fields
return HttpResponseRedirect( reverse( ...))
To start with, a very basic template for rendering a form:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
Make it work, inspect the select structure in your browser, and set to work on customizing it.
I see that forms without buttons are very popular (like here). How to create a form that will be automatically submit for two different fields in Django, after the user selects the field (example 1) or type in the text and clicks something (it means completes typing) (example 2):
1.) ChoiceField
forms.py
class Search(forms.Form):
field = forms.ChoiceField(choices=MY_CHOICES)
views.py
if request.method == "GET":
form = Search(request.GET)
if form.is_valid():
print('it's work')
template.html
<form method="GET">
{% csrf_token %}
{{ form }}
</form>
2.) CharField
forms.py
class Search(forms.Form):
field = forms.CharField(max_length=10)
* other files like above
You may simply change forms.py:
class Search(forms.Form):
field = forms.ChoiceField(choices=MY_CHOICES,
widget=forms.Select(attrs={'onchange': 'submit();'}))
Nothing else to add, no jquery needed.
See also here.
You can use jquery in your template like this:
$('#search_field').change(function(){
$('#your_form').submit()
});
or when user click on something:
$('#something').click(function(){
$('#your_form').submit()
});
I've implemented TinyMCE with the django-tinymce package. However, my submit button which worked fine without TinyMCE now has become rather useless since I can't submit the form, once everything is filled out.
I can use Ctrl + S inside of TinyMCE (I discovered that by accident) and everything will get submitted correctly. Also, I can use the save-button of the TinyMCE "save" plugin to submit.. Do I have to configure the submit button to make it work with TinyMCE?
Template:
{% extends 'medisearch/header.html' %}
{% load crispy_forms_tags %}
{% block header %}
{{ form.media }}
{% endblock %}
{% block content %}
▷⋅⋅⋅⋅⋅⋅⋅<form action="{{ url }}" method="post">
▷⋅⋅⋅⋅⋅⋅⋅ <div class="form-group">
▷⋅⋅⋅⋅⋅⋅⋅ {% csrf_token %}
▷⋅⋅⋅⋅⋅⋅⋅ {{ form|crispy }}
▷⋅⋅⋅⋅⋅⋅⋅ </div>
▷⋅⋅⋅⋅⋅⋅⋅ <input type="submit" class="btn btn-primary" value="Speichern" />
▷⋅⋅⋅⋅⋅⋅⋅</form>
{% endblock %}
views.py
class EntryDetail(DetailView):
model = Mediwiki
slug_field = 'non_proprietary_name'
template_name = 'mediwiki/entry.html'
class MediwikiForm(FormView):
template_name = 'mediwiki/create.html'
form_class = MediwikiForm⋅
success_url = "/" #TODO user get's redirected to page he's created⋅
def form_valid(self, form):
form.save()
return super(MediwikiForm, self).form_valid(form)
class EntryDisplay(View):
def get(self, request, *args, **kwargs):
try:
view = EntryDetail.as_view()
return view(request, *args, **kwargs)
except Http404: # If there's no entry in db:
if check_user_editor(request.user) == True:
view = MediwikiForm.as_view()
return view(request, *args, **kwargs)
else:
pass
def post(self, request, *args, **kwargs):
view = MediwikiForm.as_view()
return view(request, *args, **kwargs)⋅
forms.py
class MediwikiForm(ModelForm):
wiki_page = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
class Meta:
model = Mediwiki⋅
fields = '__all__'
TinyMCE is in urls.py and under INSTALLED_APPS..
I know it's probably too late for you, but it seems that i had the same issue, just now and my solution might help someone in the future.
You are using crispy, which includes the javascript files for the form on it's own.
Therefore the django_tinymce/init_tinymce.js will be referenced twice.
This will break the submittion of your content, since the form is initialized twice.
In order to fix this you may just remove the call of {{ form.media }}.
I had a similar issue and learned that it has to do with the way that TinyMCE deals with text areas. The following init script worked for me:
<script>
tinymce.init({
selector:'.editor',
setup: function (editor) {
editor.on('submit', function (e) {
editor.save();
});
}
});
</script>
#artifex_knowledge answers makes sense and it works.
To build up on it, besides calling editor.save() on submit (or on change), keep in mind that if users don't fill the text area, they won't be able to submit the form, but the this field is required error message won't be displayed.
This is because the text area field (in this case wiki_page) is required by default, so in the html it will be rendered with required. But TinyMCE hides the text area (and replaces it with an iframe :( ), so if you try to submit the form with an empty required, it won't, but the error message will keep hidden.
(A possible solution is to use JS to remove the required attribute and check it in django later).
Just delete required field from textarea element, which is used as editor.
Deleting the 'required' field in the textarea element solved my problem (like Krysits mentioned)
I also had the same issue as yours, and I just removed for instance: "wiki_page" charfield from the subclass of Modelform, and put Tinymce widget in the Meta class.
class MediwikiForm(ModelForm):
class Meta:
model = Mediwiki⋅
fields = '__all__'
widgets = {
'wiki_page': TinyMCE(attrs={'cols': 80, 'rows': 30})
}
I'm new to Django/Python and working on a webapp that queries a DB of cars based on selects/dropdowns on the home page and sends the user to a details page about the car they selected. This is done through a 'make', 'model', and 'trim' dropdown box. What I'm having trouble understanding and getting errors doing, is submitting the trim ID upon clicking a button that will submit the form. I know what needs to happen I just don't know how to do so using Django views and templates.
The make box is populated via returned queryset from IndexView. The model box is populated via jQuery/Ajax dependent upon which make was selected in the make box. The trim box is the same way, populated dependent upon what was selected in the model box. I now need to be able to submit the form (which really only needs to submit the trim ID because the trim IS the specified car) in order to show details about the car that the user has chosen.
This is the error I am getting:
Reverse for 'search' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P<trim>\\d+)/$']
This is basically what my homepage template looks like:
<form action="{% url 'search:search' trim.id %}" class="form-inline" id="dropdownText">
<div class="form-group" id="dropdownGroup">
<span style="display:inline-block" class="selectBox">
<select class="form-control" id="make">
<option value='empty'></option>
{% for make in allMakes %}
<option value="{{ make.id }}">{{ make.name }}</option>
{% endfor %}
</select>
<label for="make" style="display:block">Make</label>
</span>
<span style="display:inline-block" class="selectBox">
<select class="form-control" id="model" disabled>
<!-- List each make's model's name with JQ. -->
</select>
<label for="model" style="display:block">Model</label>
</span>
<span style="display:inline-block" class="selectBox">
<select class="form-control" id="trim" name="selectedTrim" disabled>
<!-- List all trims for each make/model with JQ. -->
</select>
<label for="trim" style="display:block">Trim</label>
</span>
</div>
<div class="text-center">
<button type="submit" class="btn btn-default" id="go">GO!</button>
</div>
</form>
URLs:
# Index
url(r'^$', views.IndexView.as_view(), name='index'),
# /trimId
url(r'^(?P<pk>\d+)/$',
DetailView.as_view(), name='detail'),
# /search
url(r'^search/(?P<trim>\d+)/$', views.search, name='search'),
# Uses Ajax/JSON to change the model/trim boxes. Use make
# and model instead of pk to pass them into the view fxns.
url(r'^getmodels/(?P<make>\d+)/', views.getModels, name='getmodels'),
url(r'^gettrims/(?P<model>\d+)/', views.getTrims, name='gettrims'),
Views:
class IndexView(generic.ListView):
template_name = 'search/index.html'
# Name of the template varible.
context_object_name = 'allMakes'
def get_queryset(self):
# Return what will be listed in index.html
return Make.objects.all()
class DetailView(generic.DetailView):
model = Trim
template_name = 'search/detail.html'
# Take in the request and the ID for the selected Make
# and return something that we can work with in JS!
def getModels(request, make):
selectedMake = Make.objects.get(id=make)
# Get the models based on what was selected as the make.
models = Model.objects.all().filter(make=selectedMake)
# Translate to JSON
jsonModels = serializers.serialize("json", models)
# Return the JSON.
return HttpResponse(jsonModels, content_type='application/javascript')
def getTrims(request, model):
selectedModel = Model.objects.get(id=model)
trims = Trim.objects.all().filter(model=selectedModel)
jsonTrims = serializers.serialize("json", trims)
return HttpResponse(jsonTrims, content_type='application/javascript')
# Can I make this redirect to the DetailView with the ID for the
# trim to show details for?
def search(request, trim):
selectedTrim = get_object_or_404(Trim, pk=trim)
context = {'trim': selectedTrim}
return render(request, 'search/detail.html', context)
That error:
Reverse for 'search' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['search/(?P<trim>\\d+)/$']
means that you didn't give the id parameter (you called it trim). It should be part of the arguments or keyword arguments.
I assume that's because there is no trim object in the template here:
<form action="{% url 'search:search' trim.id %}"
Is that template rendered via a DetailView? If that's the case the following would probably work:
<form action="{% url 'search:search' object.id %}"
The solution to the problem I was having lied in my url patterns. By taking out the ID portion of the search URL, and changing the view as such:
def search(request):
trim = request.GET['selectedTrim']
selectedTrim = get_object_or_404(Trim, id=trim)
context = {'trim': selectedTrim}
return render(request, 'search/detail.html', context)
and my form action to:
action="{% url 'search:search' %}"
I was able to successfully pass the selected trim to the view via request method, and not through the url regex variable, which was causing the error due to the selected trim ID not actually existing via context provided to the template (I think).
On my Django page I have advanced search button in main toolbar (bootstrap navbar). Clicking on this button display modal window with advanced searching options.
Actually, I have no idea how to redirect to search results view after filling the form and clicking "Search".
I've tried to use JavaScript's window.location.replace but it results in switching to AnonymousUser and I don't know how to pass form data to my SearchResultView.
In general at the moment I only have a very simple skeleton:
class SearchView(TemplateView):
"""View for displaying search results."""
template_name = 'app/search.html'
I am redirecting after submitting form using js:
<script type="text/javascript">
function search_click(event) {
event.preventDefault();
window.location.replace("http://localhost:8000/app/search");
}
</script>
But it causes that admin user is logged out and I am logged as anonymoususer.
How to pass data from form to validation and how to use it in my SearchView so I could make a query and display data ?
I also need some form for validating input data.
Any help, suggestions?
Ok, I think i solved my problem :)
In HTML before my form I put:
<form action="{% url 'search' %}" method="post">
And in my views.py:
class SearchView(TemplateView):
"""View for displaying search results."""
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)
return context
def post(self, request, *args, **kwargs):
return render(request, "app/search.html")
I am not sure only if I should inherit from FormView or find other way to get form data in my view.