How to get class variable to Django template - python

I have just started with creating Django app. I have a class in models.py, which have a class variable CATEGORY_CHOICES with values for choices field.
#models.py
from django.db import models
from django.utils import timezone
class Entry(models.Model):
CATEGORY_CHOICES = (
('c1','choice 1'),
('c2','choice 2'),
('c3','choice 3'),
('c4','choice 4'),
)
date = models.DateField(default=timezone.now)
time = models.TimeField(default=timezone.now)
category = models.CharField(choices=CATEGORY_CHOICES,blank=False,null=False,max_length=2)
value = models.TextField()
I want to make form for creting instanes of class Entry. I'm having problem with the select menu, where I want to put values from CATEGORY_CHOICES but I can't figure out how.
<!-- homepage.html -->
{% load staticfiles %}
{% load app_filters %}
<HTML>
<HEAD>
<TITLE>Website title</TITLE>
<link rel="stylesheet" href="{% static "css/app.css" %}">
</HEAD>
<BODY>
<form method="POST" class="form-inline">{% csrf_token %}
<input type="date" class="form-control" id="date-input">
<input type="time" class="form-control" id="time-input">
<select class="form-control">
{% for choice in Entry.CATEGORY_CHOICES %}
<option>{{ choice|get_at_index:1 }}</option>
{% endfor %}
</select>
<input type="text" class="form-control" id="value-input" placeholder="Value">
<input type="submit" value="OK">
</form>
</BODY>
</HTML>
It's a 4 elements list, so {% for choice in Entry.CATEGORY_CHOICES %} should be saving single 2-elements lists (first ('c1','choice 1') then ('c2','choice 2') etc) into variable choice. There I pick the second element of the list with the help od custom filter get_at_index.
#app_filters.py
from django import template
register = template.Library()
#register.filter(name='get_at_index')
def get_at_index(list, index):
return list[index]
I get no errors, but in the final form, there are no options in select menu.
What could be wrong and how to fix it?
#views.py
from django.shortcuts import render
from .forms import EntryForm
def home_page(request):
form = EntryForm()
return render(request, 'app/homepage.html', {'form':form})
And forms.py
#forms.py
from django import forms
from .models import Entry
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ('date','time','category','value',)

In your view, you're passing down the form to the template, but you don't use the form in your template the way you're supposed to. To use the form you've passed down, write your form code in the template more like this:
<form method="POST" class="form-inline">
{% csrf_token %}
{{ form }}
<input type="submit" value="OK">
</form>
And it will render the entire form for you. You can read more about it in the official documentation: Building a form in Django
Or, if you want to build the form yourself, then you need to send the coices down to your template in your view:
def home_page(request):
form = EntryForm()
return render(request, 'app/homepage.html', {
'form': form,
'entry_choices': Entry.CATEGORY_CHOICES
})
And then access it in your template using the key entry_choices.

Related

How do I implement a form submission if the form is in my base template file?

I have a base template file that holds the form for the users to subscribe to the email newsletter. All of my templates inherit from the base template file, as I'd like to display this form on every web page.
I don't know how do I make the form submit the data the user inputs into the database. So far, I dealt with views and each view was specific to a URL, so it's not really obvious to me how do I do this for all URLs, since the base template is present on all URLs.
base.html (the base template file):
{% load static %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
Homepage
Post a job
{% block content %}{% endblock %}
<p> Subscribe to new jobs: </p>
<form method="post">
<p> Email: <input type="email" name="email" /> </p>
<p> First name: <input type="text" name="first_name" /> </p>
<p> Last name: <input type="text" name="last_name" /> </p>
<input type="submit" value= "Submit">
</form>
</body>
</html>
I also made a form in my forms.py file which constructs the form from my email subscriber model, but I don't use it anywhere so far:
EmailSubscriberForm = modelform_factory(EmailSubscriber, fields=["email", "first_name", "last_name"])
How do I achieve what I want?
you need to use a ModelForm, that will link a form to a model when calling save() method. (this will add a lot of security too)
from django.forms import ModelForm
from myapp.models import EmailSubscriber
# Create the form class.
class EmailSubscriberForm(ModelForm):
# if email is an EmailField, `is_valid` method will check if it's an email
class Meta:
model = EmailSubscriber
fields = ["email", "first_name", "last_name"]
Then in the view you can create and pass as a context or get the response and save to the database
if request.method == "POST":
form = EmailSubscriberForm(request.POST)
if form.is_valid():
email_subscriber = form.save()
# generally call `return HttpResponseRedirect` here
else:
form = EmailSubscriberForm()
# generally call `return render(request, 'page.html', {'form': form})
and you just call this in your template :
<form method="post">
{{ form }}
</form>
Ref : https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/

Django - saving form to the built in database SQLite

This is my first time using Django and I am very simply trying to save text to the database. I have created the table inputs in the database.
I am getting the following error;
Error - Page not found (404)
My code is as follows;
Models.py
from django.db import models
class Input(models.Model):
waist = models.IntegerField(default=0)
height = models.IntegerField(default=0)
def __unicode__(self):
return "{0} {1} {2}".format(
self, self.waist, self.height)
forms.py
class InputForm(forms.ModelForm):
class Meta:
model = Input
fields ={
'waist',
'height'
}
views.py
def InputView(request):
if request.POST:
form = InputForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('account/input')
else:
form = InputForm()
args = {'form' : form}
return render(request,'accounts/input.html', args)
urls.py
url(r'^input/$',views.InputView, name='view_input')
input.html
{% extends 'base.html' %}
{% block head %}
<title> Edit Profile </title>
{% endblock %}
{% block body %}
<div class="container">
<h1> Enter Body Details </h1>
<br>
<br>
<form action="account/input" method="post">
{% csrf_token %}
<ul>
{{form.as_ul}}
</ul>
<input type="Submit" name="submit" value="submit"/>
</form>
</div>
{% endblock %}
If any one can help it would be greatly appreciated.
HttpResponseRedirect('account/input')
you need to add one more '/' to the beginning like
HttpResponseRedirect('/account/input')
Another way to do it is to use reverse() so if you change the URL you don't have to change your code and you avoid mistakes entering the URL.
Instead of
HttpResponseRedirect('/account/input')
use
HttpResponseRedirect(reverse('view_input'))
remember to add the import
from django.urls import reverse

Django do not render ModelForm

I am working on a little project on Django, I have had some issues on rendering ModelForm. In main.html tag {{form.ad_p}} doesn't seem working. I only see "Save" button and don't see any ModelForm fields.
If I put below code to shell
form = AddPath()
form.as_p()
I see:
form.as_p()
u'<p><label for="id_name">Name:</label> <input id="id_name" maxlength="200" name="name" type="text" /></p>\n<p><label for="id_route_data">Route data:</label> <textarea cols="40" id="id_route_data" name="route_data" rows="10">\r\n</textarea></p>'
Can you explain, what am I doing wrong?
I already searched on stackoverflow, but same problem hasn't been resolved. I hope, I'll be more lucky
models.py:
from django.db import models
from django.contrib.auth.models import User
class Path(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length='200')
route_data = models.TextField()
def __unicode__(self):
return self.name
views.py:
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.core.context_processors import csrf
from google_maps.forms import AddPath
def index(request):
args = {}
args.update(csrf(request))
form = AddPath()
return render_to_response('main.html', args)
def add_path(request):
#me = request.user
me = 'test'
if request.method == 'POST':
form = AddPath(request.POST)
if form.is_valid():
tmpForm = form.save(commit=False)
tmpForm.user = me
tmpForm.save()
return HttpResponse('Saved')
else:
return HttpResponse(form.errors)
main.html
{% extends 'basis.html' %}
{% block leftbar %}
<form action={% url 'add_path' %} method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden", id="coordinate" name="coordinate"/>
<input type="submit" name="submit" value="Save"/>
</form>
{% endblock %}

HTML tags for choicefield in Django

I cant seem to find ANYWHERE on how to do choicefield HTML tags in Django. I found radio buttons and other advance choice fields, but nothing on basic drop down HTML tags with Django. I have models.py and view.py set up passing list1 to the html pages, but cant seem to make it display anything except
<select style="width:300px">
{% for choice in list1.VIEWS %}
<option>{{choice}}</option>
{{choice}}
{% endfor %}
</select>
Help would be greatly appreciated
models.py
class preset_list(models.Model):
VIEWS = (
('1', 'X'),
('2', 'Y'),
)
query_choice = forms.ChoiceField(choices=VIEWS)
view.py
list1 = models.preset_list()
return render_to_response('services.html',
{'array':json.dumps(data, cls=SpecialEncoder),
'list1':list1},
)
ModelForms are your friend here.
models.py
class PresetList(models.Model):
VIEWS = (
('1', 'X'),
('2', 'Y'),
)
query_choice = forms.ChoiceField(choices=VIEWS)
forms.py
from django.forms import ModelForm
from . import models
class PresetListForm(ModelForm):
class Meta:
model = models.PresetList
view.py
from . import forms
def my_view(request):
preset_form = forms.PresetListForm()
return render_to_response('services.html', {
'array': json.dumps(data, cls=SpecialEncoder),
'preset_form': preset_form,
})
services.html
<form method=POST action="/somewhere">
{{ preset_form.as_p }}
</form>
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
https://docs.djangoproject.com/en/1.6/ref/forms/fields/#choicefield
Give the generic CreateView a try.
views.py
from django.views.generic.edit import CreateView
from .models import PresetList
class PresetListCreate(CreateView):
model = PresetList
presetlist_form.html
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Create" />
</form>
we can use this without using django form
<select style="width:300px" name="presen">
{% for val, name in preset_list.VIEWS %}
<option value="{{val}}">{{name}}</option>
{% endfor %}
</select>
Not sure what you want done, but if you eant to send 1 when X is displayed, the following should work:
<select style="width:300px">
{% for choice in list1.VIEWS %}
<option value={{choice.0}}>{{choice.1}}</option>
{{choice}}
{% endfor %}
</select>
You can create a form with a drop-down and tell it which values to populate it with like so:
Form
class MyDropDownForm(forms.ModelForm):
somerow = forms.ModelChoiceField(
# change this queryset if you want to limit the options
queryset= MyModel.objects.all().values('somerow'),
widget=Select(),
required=True,
)
class Meta:
model = MyModel
fields = ['somerow']
View
class MyView(DjangoTemplateView):
def get(self, request):
# you can set an instance when creating the form to set the value
# to be that of an existing row in your model
# MyDropDownForm(instance=MyModel.objects.filter(id=1))
form = MyDropDownForm()
return render_to_response('app/page.html', {'form': form})
def post(self, request):
# if you had set the instance in the get you want to do that again
form = MyDropDownForm(data=request.POST)
if form.is_valid():
return render_to_response('app/success.html')
return render_to_response('app/page.html', {'form': form})
Page.html
<form method="post">
{% csrf_token %}
{{ form.id }}
{{ form.myrow }}
{% if form.myrow.errors %}
{% for error in form.myrow.errors %}<p>{{ error }}</p>{% endfor %}
{% endif %}
<button>Submit</button>
</form>
Take a look at the docs here for more info on creating model forms.

django poplulate html form

How to set the html form fields without using django-forms.
If you do not wish to use django.forms, but get data from a model and display it into a html form, you could do something like this:
views.py
from django.shortcuts import render_to_response, redirect
from myApp.models import MyModel
def editForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
return render_to_response('formUpdate.html',{ 'model' : model })
def updateForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
model.firstname = request.POST['firstname']
model.lastname = request.POST['lastname']
model.save()
return redirect('home', message='your name has been updated')
template - formUpdate.html
{% extends "base.html" %}
{% block content %}
<form action="/updateForm/{{ model.id }}/" method="post">
First name: <input type="text" name="firstname" value="{{ model.firstname }}" /><br />
Last name: <input type="text" name="lastname" value="{{ model.lastname }}" /><br />
<input type="submit" value="submit" />
</form>
{% end block %}
models.py
from django.db import models
class MyModel(models.Model):
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'views.home', name="home"),
(r'^editForm/(?P<model_pk>\d+)/$', 'views.editForm'),
(r'^updateForm/(?P<model_pk>\d+)/$', 'views.updateForm'),
)
This is very similar to how forms are processed in PHP or similar, the model is passed into the template where the existing values are rendered. The id or pk (primary key) of the model is passed to the view via the URL and then updated values then returned to the storing view in the POST data where they can be retrieved and the updated values stored in the database.
One of the beauties of Django is how it balances speed of development with plugability - pretty much any of it's parts can be replaced or altered.
Having said this, is there a reason why you don't want to use django.forms? To my understanding a form simply performs most of the hard work in the example above for you, this is what django.forms are for. They also have other features, to help prevent malicious access of your web app, for example, OOTB. It is fairly easy to create ajax helper methods to retrieve and update them also.
You can do that as you would create a normal form in html. Just be careful to place the {% csrf_token %}. And the name of the input in the form, as they will be used in the view.
Eg:
<form method="post" action="#the url for the view">
{% csrf_token %}
...
...
<!-- fields that you want Eg: -->
<label for="username">User name:</label>
<input type="text" name="username" id="username" />
...
...
<input type="submit" value="Submit" />
</form>
Hope this helped.

Categories

Resources