How can I pass a list of items into a template?
In my views:
from django.shortcuts import render, render_to_response
from django.http import HttpResponse
from django.template import loader
from django.views.decorators.csrf import csrf_exempt
from .models import Question
from .forms import usersData1, usersData2, usersData3
def start_pr(response):
name = ["Name","Phone Number","Email"]
form = usersData1()
return render_to_response(response, "start_pr/start.html", {"form":form}, {"name":name})
In my HTML:
{% block content %}
<form action="/start/" method="post">
<legend>
{%for items in form %}
{% for obj in name %}
<p> {{ obj }} </p>
{% endfor %}
<input type="text" name="name" maxlength="20" required="" id="id_name" placeholder="{{items.name}}">
<br>
{% endfor %}
next
</legend>
</form>
{% endblock %}
In my forms:
from Django import forms
class usersData1(forms.Form):
name= forms.CharField(label="name", max_length=20)
phoneNum= forms.IntegerField(label="phoneNum")
email= forms.EmailField(label="email", max_length=50)
The list is in my views as name. I have used {% for obj in name %}<p>{{obj}}</p>.
When I go to localhost:8000 it shows an HTML form as the out product. which is weird (like opening up google view page sources when right-clicked). I am also new to Django but know how to make views and link them along with most of the basics.
What I don't know is this {%%}; what is this symbol called, and where can I find documentation on this syntax?
What I am trying to achieve in this Django view is to have 3 boxes with names from the list name as the name for that box (pretty much an iteration).
If you want to pass two (or more) elements to the template, you do that in the same dictionary:
def start_pr(response):
name = ['Name', 'Phone Number', 'Email']
form = usersData1()
return render_to_response(
response,
'start_pr/start.html',
{'form': form, 'name':name}
)
However here it looks like you simply want to add placeholders. You can simply do that in the form:
from django import forms
class UsersData1(forms.Form):
name= forms.CharField(
label='Name',
max_length=20,
widget=forms.TextInput(attrs={'placeholder': 'Name'})
)
phoneNum = forms.IntegerField(
label='Phone Number',
widget=forms.NumberInput(attrs={'placeholder': 'Phone Number'})
)
email= forms.EmailField(
label='Email',
max_length=20,
widget=forms.TextInput(attrs={'placeholder': 'Email'})
)
This will avoid complicated logic in the template which is not the purpose of a template anyway. A template is used for rendering logic.
Related
I would like to use an id to search my database for the username that belongs to that id.
I have a url.py setup to give the id via an url variable then I pass it onto the views.py that passes it to the template
At the moment I have the following:
models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
pass
def __str__(self):
return self.email
docfile = models.FileField(upload_to='static/users/',)
views.py
def ProfileView(request, id):
return render(request, 'pages/profile.html', {"id":id})
urls.py
path('profile/<int:id>', views.ProfileView, name='Profile')
profile.html
<div class="mainusers">
<div class = "userLine">
<p>{{ id.username }}</p> <!-- I know this wouldn't work, It's just a place holder at the moment -->
<center><p></p><p class="mainfont"><u>{{ id.username }}</u><p></center>
<div class="circular--portrait">
<img id="ProfileBox" src="../static/users/{{ id.username }}.gif" onerror="this.onerror=null;this.src='static/users/default.gif';"/>
</div>
<center><p><br></br> Date Joined: {{id.date_joined}}</p></center>
{% if id.is_superuser %}
<center><p>Developer</p></center>
{% endif %}
<div class="wrapper">
<button class="logout" onclick="window.location.href='{% url 'logout' %}'">Logout</button>
<button class="logout" onclick="window.location.href='/invgen'">Generate Invite Code</button>
</div>
You need to fetch the User object for that id:
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
def profile_view(request, id):
user = get_object_or_404(User, pk=id)
return render(request, 'pages/profile.html', {'id':id, 'user': user})
We can then render it like:
<img id="ProfileBox" src="../static/users/{{ user.username }}.gif" onerror="this.onerror=null;this.src='static/users/default.gif';"/>
If you make use of static files, it is however probably better to use the {% static ... %} template tag, as is described in the documentation.
Note: according tot PEP 8, one uses lowercase characters and an underscore as separator for functions, so it is probably better to rename ProfileView to profile_view, as I did here.
You can use the request object to find the logged in user i.e. request.user
Could anyone correct my code?
Background:
The user, once on the 'start.html' template, will enter their name and press submit. Then on the next template, 'game.html', there should be a paragraph tab that contains that users name.
Problem:
I must be writting something incorrectly because the user's name does not render on the 'game.html' template. Or, I could also be storing it wrong. Any suggestions or corrections would be very appreciated!
models.py - fp
from django.db import models
class Player(models.Model):
#first player name
fp_name = models.CharField(max_length=30, default='')
forms.py - I'm not sure if this is actually needed...?
from django import forms
class PlayerInfo(forms.Form):
fp_name = forms.CharField(max_length=30, label='First player name')
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, render_to_response
import os
from .forms import PlayerInfo
from .models import Player
def index(request):
return render(request, 'index.html')
def start(request):
if request.method == 'Post':
form = PlayerInfo(request.POST)
if form.is_valid():
obj = Player()
obj.fp_name = form.cleaned_data['fp_name']
return HttpResponseRedirect('/')
else:
form = PlayerInfo()
return render(request, 'start.html')
def game(request):
return render_to_response('game.html', {'obj': Player.objects.all()})
start.html - Meant to submit player one's name
{% extends 'base.html' %}
{% block botRow %}
<form method="post">
{% csrf_token %}
<label for="fp_name">First Player Name</label>
<input id="fp_name" type="text" name="fp_name" maxlength="30" required />
<input type="submit" value="Submit" />
</form>
{% endblock %}
game.html - Meant to render the player one's name
{% extends 'base.html' %}
{% block midRow %}
<p>{{ obj.fp_name }}</p>
{% endblock %}
in your game.html the obj is query set of all Users, so you should walk through the list, look on block for in the docs:
{% extends 'base.html' %}
{% block midRow %}
{% for user in obj %}
<p>{{ user.fp_name }}</p>
{% endfor %}
{% endblock %}
Using User.objects.all() you are getting a Collection of all site's users. It isn't current user. So, the collection doesn't have parameter fp_name. Use request.user to get current logged in user.
Also, there is some redundancy in your code:
Django contains User class with ability to store First Name out of the box. So, you don't need to declare it at all. https://docs.djangoproject.com/en/1.11/ref/contrib/auth/#django.contrib.auth.models.User
There is special class of forms - ModelForm. It helps you to map model's fields to form's fields as fast as possible. (https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/)
There is special class of views - CreateView. It helps you to realize basic logic of model creating. (https://docs.djangoproject.com/en/1.11/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView)
Forms intended to save your time. So, in templates it's better to use built-in rendering engine of forms, than to declare their fields manually. (https://docs.djangoproject.com/en/1.11/topics/forms/#the-template)
If game.html is permitted only for registered users it's a good idea to use #login_required decorator to restrict access to this part of the site.
In my Django app in a Createview class it never enters the is_valid(): statement and I can not seem to find any errors:
models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.conf import settings
from .validators import validate_file_extension
import zipfile
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField(max_length=250)
date = models.DateTimeField(auto_now=True, auto_now_add=False)
album_image = models.FileField(validators=[validate_file_extension])
user = models.ForeignKey(User, default=1)
face = models.IntegerField(default=1)
def get_absolute_url(self):
return reverse('photos:detail',kwargs={'pk':self.pk})
def __str__(self):
return self.title
views.py
This is my view folder that contains a list view a detailed view and create view. Although the form doesnt pass the valid test, it still gets uploaded and is viewable by the user
from django.http import Http404
from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404
from django.core.urlresolvers import reverse
from .forms import PostForm
from .models import Post
from django.contrib.auth.models import User
from django.template import loader
from django.views import generic
from django.views.generic.edit import CreateView
import cognitive_face as CF
import json
class IndexView(generic.ListView):
template_name='photos/post.html'
def get_queryset(self):
return Post.objects.filter(user=self.request.user)
class DetailView(generic.DetailView):
model = Post
template_name = 'photos/detail.html'
class PostCreate(generic.CreateView):
form = PostForm()
model = Post
if form.is_valid():
print('valid')
instance = form.save(commit=False)
username = form.cleaned_data['username']
album_image = form.cleaned_data['album_image']
instance.save()
if not form.is_valid():
print('not')
post_form.html
<html>
<body>
{% if request.user.is_authenticated%}
<h3>Hello {{request.user.username}}, please upload your image as either a .JPEG, .GIF or .PNG</h3>
{% endif %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
{% if request.user.is_authenticated %}
<form class="form-horizontal" role="form" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
{{ form.errors }}
{{ form.non_field_errors }}
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
{% else %}
<p>You must be logged in to upload a file</p>
{% endif %}
</div>
</div>
</div>
</body>
</html>
urls.py
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from photos.models import Post
from . import views
app_name = 'photos'
urlpatterns = [
url(r'^$',views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$',views.DetailView.as_view(), name='detail'),
url(r'post/add/$', views.PostCreate.as_view(), name='post-add'),
]
You are writing function based view code inside a class based view, which is incorrect.
You shouldn't need to instantiate the form, or manually check whether it is valid. Just set form_class for the view, then override form_valid or form_invalid if you need to change the behaviour when the form is valid or invalid. Since you have {{ form.errors }} in your template, it should show any errors when you submit the form.
class PostCreate(generic.CreateView):
form_class = PostForm
model = Post
See the docs on form handling with class based views for more information. You might find it easier to write a function based view to begin with, since the flow of the code is easier to follow.
I am building a web application on django. As part of this, I have created one html form like following:
<form method="post" action="/voting/add_state/">{% csrf_token %}
State name:<br>
<input type="text" name="state_name"><br>
<input type="submit" value="Submit">
</form>
In models.py I have added unique constraint validation on name like following:
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
So for duplicate name, it throws a unique constraint error which I would like to capture in the template. Can anyone please give any suggestion.
Create a form based on your model
#forms.py
from django import forms
from .models import State
class StateForm(forms.ModelForm):
class Meta:
model = State
fields = ('name',)
now use this form on your views
#views.py
from django.views.generic import FormView
from .forms import StateForm
class MyView(FormView):
template_name = 'template.html'
form_class = StateForm
success_url = '/my-url-to-redirect-after-submit/'
template.html
<form method="post">
{% csrf_token %}
Name
{{ form.name }}
{{ form.name.errors }}
<input type="submit" value="Create">
</form>
Django has Form processing built in. Django has "Model Forms", which automatically render the form for your model. If you pass it through the view and reference it in the context it will automatically generate the html for you, but if you would like more control over what is rendered in the template then you can reference the form attributes that Django Model Form produces.
I strongly suggest working within the framework Django provides to you for building forms; it provides a lot of boilerplate code for building, validating and abstracting forms and is especially competent for simple forms like these.
Here is an example:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
class StateForm(forms.ModelForm):
model = State
fields = (name,)
views.py
from django.views.generic.edit import FormView
class StateForm(FormView):
template_name = 'state_form.html'
form_class = StateForm
success_url = '/thanks/'
state_form.html (example of auto generated form)
{{ form }}
state_form.html (example of custom form)
<form action="/" method="post">
{% csrf_token %}
{{ form.errors }}
{% for field in form %}
<input type="{{ field.type }}" name='{{ field.name }}' class="submit" value="{{ field.value}}">
{% endfor %}
<input type="submit" name='submit" value="Submit">
</form>
References:
Django Forms:
https://docs.djangoproject.com/en/1.9/topics/forms/
Django Model Forms: https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/
Django Generic Views:
https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView
You could create a form for State model and create the validator, so if the user try with a duplicate name, the form raise a message something like this:
models.py
class State(models.Model):
name = models.CharField(max_length=200, unique=True)
vote_counted = models.BooleanField(default=False)
forms.py
def unique_name(value):
exist = State.objects.filter(name=value)
if exist:
raise ValidationError(u"A state with the name %s already exist" % value)
class StateForm(forms.Form):
name = forms.CharField(label=('Name:'), validators=[unique_name])
Then you just need to render the StateForm in the template.
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 :) .