Jeeves Jeeves - 3 months ago 21
Python Question

Form input-box not displaying

I'm trying to display a simple form input-text box with Django. I'm am deploying on Amazon AWS. The site works fine on a different server (pythonanywhere) but there is a major problem on AWS. Specifically, the input box is not being displayed. I'm using templates as follows:

home.html

{% extends 'lists/base.html' %}

{% block header_text %}Start a new To-Do list {% endblock %}

{% block form_action %}{% url 'new_list' %}{% endblock %}


base.html

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta http-equiv="X UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>To-Do lists</title>
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/base.css" rel="stylesheet">
</head>
<body>
<div class="container">

<div class="row">
<div class="col-md-6 col-md-offset-3 jumbotron">
<div class="text-center">
<h1>{% block header_text %}{% endblock %}</h1>
<form method="POST" action="{% block form_action %}{% endblock %}">
{{ form.text }}
{% csrf_token %}
{% if form.errors %}
<div class = "form-group has-error">
<span class = "help-block">{{ form.text.errors }}</span>
</div>
{% endif %}
</form>
</div>
</div>
</div>

<div class="row">
<div class="col-md-6 col-md-offset-3">
{% block table %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>


models.py

from django.db import models
from django

.core.urlresolvers import reverse


class List(models.Model):
def get_absolute_url(self):
return reverse('view_list', args=[self.id])

# Create your models here.
class Item(models.Model):
text = models.TextField(default = '')
list = models.ForeignKey(List, default = None)
#list = models.ForeignKey(List , default=None)


forms.py

from django import forms

from lists.models import Item

EMPTY_ITEM_ERROR = "You can't have an empty list item"
class ItemForm(forms.models.ModelForm):
class Meta:
model = Item
fields = ('text',)
widgets ={
'text' : forms.fields.TextInput(attrs={
'placeholder': 'Enter a to-do item',
'class': 'form-control input-lg',
}),
}
error_messages = {
'text' : { 'required': EMPTY_ITEM_ERROR }
}


views.py

from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List

# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})


urls.py

from django.conf.urls import url
from lists import views

urlpatterns = [
url(r'^new$', views.new_list, name='new_list'),
url(r'^(\d+)/$', views.view_list, name='view_list'),

]


Currently the site displays the following:

enter image description here

However it should (and does on a different website) display this: enter image description here

I've pushed/pulled the entire project to github and the code between each site is identical, yet I'm not seeing why the text input isn't displayed, unless the form needs to be initialized in Django somehow or a quirk to AWS?

When comparing the two sites, the one without the text-box does not generate the following:

<input class="form-control input-lg" id="id_text" name="text" placeholder="Enter a to-do item" type="text" />


Even though it should, per the base.html syntax.

Updated

The full views.py (per suggested comment) is:

from django.shortcuts import redirect, render
from lists.models import Item, List
from django.core.exceptions import ValidationError
from lists.forms import ItemForm
from lists.models import Item, List

# Create your views here.
def home_page(request):
return render(request, 'lists/home.html', {'form': ItemForm()})

def new_list(request):
form = ItemForm(data=request.POST)
if form.is_valid():
list_ = List.objects.create()
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
else:
return render(request, 'lists/home.html', {"form": form})

def view_list(request, list_id):
list_ = List.objects.get(id=list_id)
form = ItemForm()

if request.method == 'POST':
form = ItemForm(data=request.POST)
if form.is_valid():
Item.objects.create(text=request.POST['text'], list=list_)
return redirect(list_)
return render(request, 'lists/list.html', {'list': list_, "form": form})

Answer

In my experience with Django, there are 2 things you often (always?) need to do to get static files to "refresh" after pushing them to a remote server:

  1. Run ./manage.py collectstatic to make sure all your static files are in the right place.
  2. While sshed into your server run the command sudo reboot now to restart your server (note that this will kick you out of your ssh session, and your server will be unreachable for a moment - usually just a few seconds in my case).

As for step 2 there might be a better way to do this, but in my experience, when I update static files the updated version is not served until I do this, and restarting nginx or the like is not sufficient for the changes to take effect. Note that this will mean that your site, if live, will not be reachable for a few seconds while the server is restarting (which is what makes me think there might be a better way to do it) but for me and my small user base this is not a big issue.

From reading some other posts about static files not updating, it seems like it could also be the case that your browser is caching the static files, and that restarting your browser/clearing the cache might do the trick as well, but I have not had a chance to try this yet.