Django Form Fields arent displayed - python

I want to display to simple search Forms in a view.
forms.py:
from django import forms
from django.utils.translation import gettext_lazy as _
class Vehicle_Search_by_VIN(forms.Form):
vin = models.CharField(max_length=17)
first_registration_date = models.DateField()
class Vehicle_Search_by_Plate(forms.Form):
plate = models.CharField(max_length=7)
last_four_diggits_of_vin = models.DateField(max_length=4)
views.py:
from django.shortcuts import render
from django.views import View
from .forms import *
class VehicleSearch(View):
template = 'vehicle_search_template.html'
cxt = {
'Search_by_VIN': Vehicle_Search_by_VIN(),
'Search_by_Plate': Vehicle_Search_by_Plate()
}
def get(self, request):
return render(request, self.template, self.cxt)
my template-file:
<form class="by_vin" method="POST" action="">
{% csrf_token %}
{{ Search_by_VIN.as_p }}
<button name='action' value='login' type="submit">Suchen</button>
</form>
<form class="by_plate" method="POST" action="">
{% csrf_token %}
{{ Search_by_Plate.as_p }}
<button name='action' value='signup' type="submit">Suchen</button>
</form>
But as a result only the submit buttons are displayed in the view. Does anybody know why my forms aren't being rendered?

in views.py, i think, you are missing *args and **kwargs parameters in get() function
class VehicleSearch(View):
template = 'vehicle_search_template.html'
cxt = {
'Search_by_VIN': Vehicle_Search_by_VIN(),
'Search_by_Plate': Vehicle_Search_by_Plate()
}
def get(self, request, *args, **kwargs): # HERE
return render(request, self.template, self.cxt)
Update
By default, class-based views does only support a single form per view but you can counter this limitation with few options depending on your logic. refer to this thread Django: Can class-based views accept two forms at a time?

try to give full path in your template variable for e.g. if your app name is my_app then template = 'my app/vehicle_search_template.html'

Related

Django: ModelForm and show data on the same url

I'm new to django and trying to create my first app and I think I might need some little help :)
I have a ModelForm on a site to submit and want to show the data on the same page. I'm having trouble to set up two functions on the same page, I think i might have to use a class and set it in urls.py but I'm not able to make it work :( the code looks like this:
forms.py:
from django import forms
from .models import Eintrag
class NameForm(forms.ModelForm):
class Meta:
model = Eintrag
fields = ['Anmeldung', 'Essen']
urls.py
from django.urls import path
from . import views
app_name = 'form'
urlpatterns = [
path('', views.get_name, name='form'),
]
views.py
from django.shortcuts import render
from django.utils import timezone
from django.contrib.auth.decorators import login_required
from .forms import NameForm
from .models import Eintrag
#login_required()
def get_name(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 = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
eintrag = form.save(commit=False)
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
eintrag.Name = request.user # Set the user object here
eintrag.pub_date = timezone.now() # Set the user object here
eintrag.save()
return render(request, 'form/name.html', {'form': form})
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'form/name.html', {'form': form})
def post_list(request):
posts = Eintrag.objects.all()
return render('form/post_list.html', {'posts': posts})
name.html
...
{% include "form/post_list.html" %}
<form action="/form/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
...
post_list.html
{% for post in posts %}
{{ post }}
{% endfor %}
So the problem is in urls.py only get_name is handled and I'm clueless how I should include post_list. I rather not want to use different url's, do I have to?
Thanks for any help and advice!
You don't need a separate URL or view for the list. Just include the queryset in the context of your get_name view.
posts = Eintrag.objects.all()
return render(request, 'form/name.html', {'form': form, 'posts': posts})
with [Class Based View] it would be better.
But with your view, you can send multiple data via context.
#login_required()
def get_name(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:
''' codes '''
eintrag.save()
return HttpResponseRedirect(request.path) # generate an empty form
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
posts = Eintrag.objects.all() # the queryset is here, and sent via context
return render(request, 'form/name.html', {'form': form,'posts':posts})
I your html remain the same, but keep your form action='' empty
{% include "form/post_list.html" %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>

How can I call multiple views in one url address in Django?

I'm trying to show forms defined by new_measurement on index.html, but I only manage to get IndexView() to work. I tried various combinations between IndexView() and new_measurement(), but those didn't work out at all. I know that IndexView() doesn't pass anything related to new_measurement(), and new_measurement() isn't called, which is the core of my problem. I'd really appreciate if someone more experienced with Django could tell me what I could, or should do. Thank you.
Here's my views.py:
from django.shortcuts import render
from django.utils import timezone
from .models import Measurement
from .forms import MeasurementForm
from django.views import generic
class IndexView(generic.ListView):
model = Measurement
context_object_name = 'measurement_list'
template_name = 'index.html'
queryset = Measurement.objects.all()
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
forms.py:
class MeasurementForm(forms.ModelForm):
class Meta:
model = Measurement
fields = ('measurement_value', 'measurement_unit')
index.html:
{% extends "base.html" %}
{% block content %}
<h1>Climate Measurement Tool</h1>
<h2>Add a new measurement</h2>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save">Add</button>
</form>
<h2>Measurements</h2>
{% if measurement_list %}
<ul>
{% for measurement in measurement_list %}
<li>
<p>{{ measurement }}</p>
</li>
{% endfor %}
</ul>
{% else %}
<p>No measurements yet</p>
{% endif %}
{% endblock %}
You can't map multiple views in one url but you can do mutiple works in one view.
update your views.py as you can see that I am sending (querylist and form) both in that view
views.py
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
qs = Measurement.objects.all()
context = {'form': form, 'measurement_list': qs}
return render(request, 'index.html', context)
update urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.new_measurement, name='index'),
]
You can't call 2 views for one url. basically each url has to be linked to one view and that's something you can't really change.
But if you want your code to be cleaner and have multiple functions, you can call them in your view, basically what you can do is to make a view and call it when a url or even more than one url has been used and in that view decide which function to use
Example:
def god_view(request):
if request.method == "POST"
return post_func(request)
return get_func(request)
This is a very simple example but you can do so many other things.
It is not possible to have more views in one url, but you can simulate it. I did it like a view and in the template of this view was javascript which loaded the second view with the response of AJAX and filled the belonging element with the second view's content. The second view was not whole template but it started with some div tags which were placed into the first template. I'll try to give you an example
views
def first_view(request):
return render(
request,
'first_template.html',
{
'first_content': 'Some heavy content'
})
def second_view(request):
return render(
request,
'second_template.html',
{
'second_content': 'Some heavier content!'
})
first_template.html
...
<body>
<div id="1">
{{ first_content }}
</div>
<div>
... loading ...
</div>
<script>
window.onload = function() {
$.ajax({
url: {% url 'to_second_view' %},
method: 'GET',
success: function(response) {
$('#2').html(response);
}
})
}
</script>
</body>
...
second_template.html
<div>
{{ second_content }}
</div>
If you're using cbv you can override the get_template_names method for any view that inherits TemplateResponseMixin and return a list of string which are searched in order until one matches or ImporperlyConfigured is raised. For example:
class SomeView(TemplateResponseMixin):
...
def get_template_names(self):
if self.request.method == "POST":
return ['post_template.html']
else:
return ['template.html']
Instead of generic.ListView you can try with rest_framework.views.APIView
from rest_framework.views import APIView
class IndexView(APIView):
def post(self, request: Request):
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
return render(request, 'index.html', {'form': form})
def get(self, request: Request):
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
This gives you more control on the APIs you call. Also you can raise/return error when you call your API using incorrect methods (PUT, PATCH)

Getting forms to display in HTML with Django

so I've gotten forms to display correctly before, I'm just a little lost as to why I am using certain words when doing so, and I'm wondering why I've used different words to get different forms to display.
In this first example (colorist_form.html) I am using {{ form }} which does get the form to display
{% extends "base.html" %}
{% block content %}
<div class="colorset-base">
<h2>Create new post</h2>
<p class="hint">Add hex codes for each color you would like to include.</p>
<form id="postForm" action="{% url 'colorsets:new_color' %}" method="POST">
{% csrf_token %}
{{ form }}
<button type="submit" class="submit btn btn-primary btn-large">Add Color Set</button>
</form>
</div>
{% endblock %}
However, in this example (widget_form.html) I am using the same {{ form }} but now the form does not display
{% block content %}
<div class="colorset-base">
<h2>Create new widget</h2>
<form id="postForm" action="{% url 'adminpanel:create-widget' %}" method="POST">
{% csrf_token %}
{{ form }}
<button type="submit" class="submit btn btn-primary btn-large">Add Widget</button>
</form>
</div>
{% endblock %}
Also in my register.html I am using {{ user_form }} which does get the form to display.
{% extends "base.html" %}
{% block content %}
<div class="form-base">
{% if registered %}
<h1>Thank you for registering!</h1>
{% else %}
<h2>Register</h2>
<form method="POST">
{% csrf_token %}
{{ user_form }}
<input type="submit" value="Register" />
</form>
{% endif %}
</div>
{% endblock %}
Why do I use the keyword "form" vs some other word such as "user_form" or "widget_form"? And why won't the widget_form.html display the form?
Here is my code for the forms and views respectively:
adminpanel app views.py:
from django.shortcuts import render
from adminpanel.forms import WidgetForm
from adminpanel.models import Widget
from django.utils import timezone
from django.contrib.auth import authenticate,login,logout
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse,reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from braces.views import SelectRelatedMixin
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
# Create your views here.
class CreateWidgetView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'index.html'
form_class = WidgetForm
model = Widget
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.save()
return super().form_valid(form)
class SettingsListView(ListView):
model = Widget
def get_query(self):
return Widget.object.filter(order_by('widget_order'))
class DeleteWidget(LoginRequiredMixin,SelectRelatedMixin,DeleteView):
model = Widget
select_related = ('Widget',)
success_url = reverse_lazy('settings')
def get_queryset(self):
queryset = super().get_query()
return queryset.filter(user_id=self.request.user.id)
def delete(self):
return super().delete(*args,**kwargs)
colorsets app views.py:
from django.shortcuts import render
from colorsets.forms import ColorForm
from colorsets import models
from colorsets.models import ColorSet
from django.utils import timezone
from django.contrib.auth import authenticate,login,logout
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse,reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from braces.views import SelectRelatedMixin
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
# Create your views here.
#def index(request):
# return render(request,'index.html')
class PostListView(ListView):
model = ColorSet
def get_queryset(self):
return ColorSet.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
class CreateColorSetView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'index.html'
form_class = ColorForm
model = ColorSet
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class DeletePost(LoginRequiredMixin,SelectRelatedMixin,DeleteView):
model = models.ColorSet
select_related = ('user',)
success_url = reverse_lazy('index')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self,*args,**kwargs):
return super().delete(*args,**kwargs)
adminpanel app forms.py:
from django import forms
from adminpanel.models import Widget
class WidgetForm(forms.ModelForm):
class Meta():
model = Widget
fields = ('name','widget_order','body')
widgets = {
'name':forms.TextInput(attrs={'class':'text-input'}),
'body':forms.Textarea(attrs={'class':'text-area'}),
}
colorsets app forms.py:
from django import forms
from colorsets.models import ColorSet
class ColorForm(forms.ModelForm):
class Meta():
model = ColorSet
fields = ('name','color_one','color_two','color_three','color_four','color_five')
widgets = {
'name':forms.TextInput(attrs={'class':'colorset-name'}),
'color_one':forms.TextInput(attrs={'class':'colorset-color'}),
'color_two':forms.TextInput(attrs={'class':'colorset-color'}),
'color_three':forms.TextInput(attrs={'class':'colorset-color'}),
'color_four':forms.TextInput(attrs={'class':'colorset-color'}),
'color_five':forms.TextInput(attrs={'class':'colorset-color'}),
}
Not sure that all that code was needed for this problem but figured it couldn't hurt.
I'm a little lost (even though I've gotten this to work in the past) so any help would be most appreciated.
If you use create view you don't have to write the form, automatically Django generate the modelform so should be something like:
class CreateWidgetView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'index.html'
model = Widget
fields = ['field', 'field2']
def form_valid(self,form): #I Think this part is not neccesary
self.object = form.save(commit=False)
self.object.save()
return super().form_valid(form)

Include template form to django admin

Is it possible to include model form template in django admin as follows?
models.py
class Customer(models.Model):
name = models.CharField(max_length=20)
designation = models.CharField(max_length=20)
gender = models.BooleanField()
forms.py
class CustomerForm(forms.ModelForm)
gender = forms.TypedChoiceField(
choices=GENDER_CHOICES, widget=forms.RadioSelect(renderer=HorizontalRadioRenderer), coerce=int, )
class Meta:
model = Customer
template.html
<form action="{% url 'verinc.views.customerView' %}" method="POST">{% csrf_token %}
{{ form.as_p }}
<input id="submit" type="button" value="Click" /></form>
views.py
def customerView(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
else:
form = CustomerForm()
return render_to_response('myapp/template.html', {'form' : form,})
admin.py
class CustomerInline(admin.StackedInline)
model= Customer
form = CustomerForm
template = 'myapp/template.html
When I view the form in url (localhost/myapp/customer) it displays all the fields correctly. But when I view it in admin page it displays only the submit button in the block. My requirement is to view the form using templates in admin page, so that i could use some AJAX script for further process. Any help is most appreciated.
Well , Its not possible . But you can implement like this :
You should create file called admin_views.py in your app customer.
Then add url in your urls.py like
(r'^admin/customer/customerView/$', 'myapp.customer.admin_views.customerView'),
Write your view implementation inside admin_views.py like :
from myapp.customer.models import Customer
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.admin.views.decorators import staff_member_required
def customerView(request):
return render_to_response(
"admin/customer/template.html",
{'custom_context' : {}},
RequestContext(request, {}),
)
customerView = staff_member_required(customerView)
And inside your admin template extend base_site.html like this one :
{% extends "admin/base_site.html" %}
{% block title %}Custmer admin view{% endblock %}
{% block content %}
<div id="content-main">
your content from context or static / dynamic...
</div>
{% endblock %}
Thats it . hit that new url after admin login . Note Not Tested :) .

newbie Django Choicefield/Charfield display on html page

I have been reading the django book and the django documentation, but still can figure it out.
i have this model.py:
from django.db import models
from django.forms import ModelForm
class Zonas(models.Model):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
class ZonasForm(ModelForm):
class Meta:
model = Zonas
this view.py:
from django import forms
from testApp.models import Zonas
from django.shortcuts import render_to_response
def menuForm (request):
z = list (Zonas.objects.all())
numbers = forms.CharField(max_length=30,
widget=forms.Select(choices=z))
return render_to_response('hello.html', {'numbers':numbers})
this html:
<html>
<body>
<form action="" method="get">
<div class="field">
{{ form.numbers }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
Ans this urls.py:
from django.conf.urls import patterns, include, url
from testApp.views import menuForm
urlpatterns = patterns('',
url(r'^hello/$', menuForm ),
)
All i get when i run the server is a page only with the submit button, and no form.number wich is supossed to be a select menu.
I tried this views.py:
def menuForm (request):
z = list (Zonas.objects.all())
numbers = forms.ChoiceField(choices=z)
return render_to_response('hello.html', {'numbers':numbers})
But the result is the same...
Any hints? Should i use a diferent return?
You are trying to access {{ form.numbers }} when you never pass a form variable to the template. You would need to access numbers directly with {{ numbers }}.
Also you aren't quite using forms correctly. Check this out https://docs.djangoproject.com/en/dev/topics/forms/
Create a menu form that contains a ModelChoiceField
forms.py
class MenuForm(Form):
zonas = forms.ModelChoiceField(queryset=Zonas.objects.all())
Now use that form in your view
views.py
from myapp.forms import MenuForm
def menuForm(request):
if request.method == 'POST': # If the form has been submitted...
form = MenuForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# Process the data in form.cleaned_data
# ...
return HttpResponseRedirect('/success/') # Redirect after POST
else:
form = MenuForm() # An unbound form
return render(request, 'hello.html', {
'form': form,
})
Now you can use the form in your template
hello.html
<html>
<body>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
</body>
</html>
How about using ModelChoiceField? This code works for me.
views.py:
from django import forms
from models import Zonas
from django.shortcuts import render_to_response
class NumbersForm(forms.Form):
numbers = forms.ModelChoiceField(queryset=Zonas.objects.all())
def menuForm(request):
form = NumbersForm()
return render_to_response('hello.html', {'form': form})
hello.html:
<form action="" method="get">
<div class="field">
{{ form.as_p }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
You have several errors in your applications. Let's do the following:
You will need the following files in your testApp folder: models.py, views.py, forms.py. Now, inside models.py you will define model Zonas (pretty much as you have done)
#models.py
from django.db import models
class Zonas(models.Model):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
Now, inside the forms.py file you will have this:
from testApp.models import Zonas
from django.forms import ModelForm
z = ((zona.name,zona.name) for zona in Zonas.objects.all())
class ZonasForm(ModelForm):
name = forms.CharField(max_length=30,widget=forms.Select(choices=z))
class Meta:
model = Zonas
Then, your views.py:
from testApp.forms import ZonasForm
from django.shortcuts import render_to_response
def menuForm (request):
if request.method = 'POST':
form = ZonasForm(request.POST)
if form.is_valid():
form.save()
else:
form = ZonasForm()
return render_to_response('hello.html', {'form':form})
There you have your form processed and everything.
Next, your hello.html:
<form action="" method="post">
{% csrf_token %}
<div class="field">
{{ form.as_p }}
</div>
<input type="submit" value="Submit">
</form>
</body>
All of this combined should work. You had some concept errors in your app definition, I hope this could help as a guide.

Categories