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:
However it should (and does on a different website) display this:
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})
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:
Run ./manage.py collectstatic to make sure all your static files are in the right place.
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.
Related
I'm working on a django bookstore website and there seems to be an error with stripe integration. I have an orders page that asks for payment information (I'm using the test API for now). I get the same error "You did not set a valid publishable key. Call Stripe.setPublishableKey() with your publishable key."
orders/views.py
from django.conf import settings
from django.views.generic.base import TemplateView
class OrdersPageView(TemplateView):
template_name = 'orders/purchase.html'
def get_context_data(self, **kwargs):
##Stripe.setPublishableKey('PUBLISHABLE_KEY')
context = super().get_context_data(**kwargs)
context['stripe_key'] = settings.STRIPE_TEST_PUBLISHABLE_KEY
return context
templates/orders/purchase.html
{% extends '_base.html' %}
{% block title %}Orders{% endblock title %}
{% block content %}
<h1>Orders page</h1>
<p>Buy for $39.00</p>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_key }}"
data-description="All Books"
data-amount="3900"
data-locale="auto">
</script>
{% endblock content %}
In your forms you need a {% csrf_token %} and form action that takes you to the charge page.
<form action="{% url 'charge' %}" method="post">
{% csrf_token %}
<h1>Orders page</h1>
<p>Buy for $39.00</p>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_key }}"
data-description="All Books"
data-amount="3900"
data-locale="auto">
</script>
</form>
Also unless never set your pricing in your templates, this is asking for trouble. Set them in your view.
I am trying to implement django-autocomplete-light in my projects but cannot figure out why it does not show me the autocomplete widget, but keeps showing an empty dropdown.
I followed the tutorial: https://django-autocomplete-light.readthedocs.io/en/3.1.3/tutorial.html.
I found that this problem has occurred in other stackoverflow questions, but none of those answers have helped me so far.
I have the following model:
class Vilt(models.Model):
vilt_title = models.CharField(max_length=200, unique=True)
I created this autocomplete view:
class ViltAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
# if not self.request.user.is_authenticated():
# return Vilt.objects.none()
qs = Vilt.objects.all().order_by('vilt_title')
if self.q:
qs = qs.filter(vilt_title__istartswith=self.q)
return qs
I use this ModelForm where I specify the widget.
from .models import Vilt
from dal import autocomplete
class ViltSearchForm(forms.ModelForm):
vilt_title = forms.ModelChoiceField(
queryset = Vilt.objects.all(),
widget = autocomplete.ModelSelect2(url='vilt-autocomplete')
)
class Meta:
model = Vilt
fields = ('vilt_title',)
from .views import (ViltAutocomplete,
)
urlpatterns = [
#other paths
path('vilt/autocomplete/', ViltAutocomplete.as_view(), name='vilt-autocomplete'),
#other paths
]
{% extends "bierviltje/base.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
#other forms
<div>
<form action="" method="post">
{% csrf_token %}
{{ vilt_search_form|crispy }}
<input type="submit" />
</form>
</div>
#other forms
</div>
{% endblock content %}
{% block javascript %}
{{ vilt_search_form.media }}
{% endblock javascript %}
This is the Javascript that is loaded in before the javascript block in base.html:
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
{% block javascript %}
{% endblock javascript %}
It's been sometime since you posted your query. But in case you have not found the answer yet, here is the solution:
In your ModelForm "ViltSearchForm", please change the widget from:
widget = autocomplete.ModelSelect2(url='vilt-autocomplete')
to:
widget = autocomplete.ListSelect2(url='vilt-autocomplete')
However, if I may add here, I can't fathom the reason for using "autocomplete" on a stand alone model.
A feedback would be much appreciated.
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
I'm trying to set up a form on Django that displays inputs on the page, but I get this error.
django.db.utils.OperationalError: no such table: firstapp_post
This doesn't happen right away, but when I try to use the submit feature on my form.
Right now this is what I have as my models:
from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
post = models.CharField(max_length=500)
user = models.ForeignKey(User)
These are currently my forms:
from django import forms
from firstapp.models import Post
class IndexForm(forms.ModelForm):
post = forms.CharField()
class Meta:
model = Post
fields = ('post',)
This is my views file:
from django.shortcuts import render, redirect
from firstapp.forms import IndexForm
from django.views.generic import TemplateView
class HomePage(TemplateView):
template_name = 'home/home.html'
def get(self, request):
form = IndexForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = IndexForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
text = form.cleaned_data['post']
form = IndexForm()
return redirect('home:home')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
This is my base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Assignment 4</title>
<link rel='stylesheet' href='{% static "css/base.css" %}'/>
</head>
<body>
<p>{{ variable }}</p>
{% block body %}{% endblock %}
<script src= '{% static "js/base.js" %}'></script>
</body>
</html>
and my home.html:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<p>Home</p>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
<p>{{ text }}</p>
</div>
{% endblock %}
Does anyone have any idea what this error even means or why I'm getting it? This has been driving me nuts. Thanks for the help!
As the error message mentions, that particular table does not exist in your database.
You can run the following command:
python manage.py makemigrations appname
By running makemigrations, you’re telling Django that you’ve made some changes to your models and that you’d like the changes to be stored as a migration.
Now run migrate again to create those model tables in your database
python manage.py migrate
Further Reading
I want to use TinyMCE in my Django project, after doing all the necessary settings, when I visit the page, the form only render normal django form but not TinyMCE rich text form. Below are my settings.
I copied tinymce folder to media folder:
C:/Python27/Scripts/nate/media/js/tiny_mce
Settings.py
TINYMCE_JS_URL = '/media/js/tiny_mce/tiny_mce.js/'
TINYMCE_DEFAULT_CONFIG = {
'plugins': "table,spellchecker,paste,searchreplace",
'theme': "advanced",
'cleanup_on_startup': True,
'custom_undo_redo_levels': 10,
}
TINYMCE_SPELLCHECKER = True
TINYMCE_COMPRESSOR = True
urls.py
(r'^tinymce/', include('tinymce.urls')),
Models
class Finmall(models.Model):
user=models.ForeignKey(User)
name=models.CharField(max_length=250, unique=True)
content1 = models.TextField()
content2 = models.TextField()
def __unicode__(self):
return self.user
Template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}
How can I make the content1 and content2 display TinyMCE rich text form?
An Example from the Documentation:
from django import forms
from tinymce.widgets import TinyMCE
class FinmallForm(forms.ModelForm):
...
content = forms.CharField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))
...
class Meta:
model = Finmall
The problem is that you are displaying the form as a Django form.
The rich edit text field will be a JS thing which Django will not create. The django.form feature will be create a HTML element.
I suggest manually putting the rich edit in to the template. As long as you give the rich edit the same "name" as the Django form element you can use it in the POST which is returned.
EDIT: You are publishing a models.TextField() when the form is rendered. This will generate a element in the form. This form will have only default properties.
I am not 100% sure how TinyMCE works but you would need to bind it to that element though a "id" or "name" value or just put the forms code in yourself into the template.
I myself do not use Django to render the forms I create forms myself in the template and give them the same names what Django would give them.
Look at the source code for the rendered page and see what the form looks like. Then set up a test page with TinyMCE and get it working and look at the difference between the element.
:)
Try to put above form {{ form.media }} i.e. {{ FinmallForm.media }} in your template
<head>
<script type="text/javascript" src="{{ MEDIA_URL }}/js/tiny_mce/tiny_mce.js"></script>
</script>
</head>
{% block content %}
<div id="postcribbody" class="wrapper">
<p class="list">You can make it</p>
{{ FinmallForm.media }}
<form enctype="multipart/form-data" form action="." method="POST">
{% csrf_token %}
{{ FinmallForm.as_p }}
<input type="submit" class="cribput" value="Submit"/>
</form>
</div>
{% endblock %}