I using Django with widgets to get some user input but I can't seem to get it to display even thou the code seems almost identical to examples online.
forms.py
from django import forms
class PickerIDForm(forms.Form):
pickeID = forms.NumberInput()
views.py
def get_id(request):
template = loader.get_template('metrics/lance1.html')
def get(self, request):
form = PickerIDForm()
return render(request, 'self.template', {'form': form})
context ={
}
return HttpResponse(template.render(context,request))
urls.py
from django.urls import path
from . import views
from . import mark_views
app_name = 'metrics'
urlpatterns = [
path('', views.index, name='index'),
path('test/', views.get_id, name='get_id'),
]
test.html
{% extends 'base.html' %}
{% block content %}
<p>User Input</p>
<form method = "post" >
{% csrf_token %}
{{form.as_p}}
<button type="submit"> Submit </button>
</form>
{% endblock %}
I'm never directly calling the get function as defined in views.py that to me seems to be a possible source of the input fields not showing up when I load up test.html
At what point do you link the disparate parts together? Because it seems I'm missing something.
You have defined the widget instead of the field in your form.
To fix that replace pickeID = forms.NumberInput() with pickeID = forms.IntegerField()
And also write your view like this:
def get_id(request):
form = PickerIDForm()
return render(request, 'metrics/lance1.html', {'form': form})
Related
I am new to Django and I am trying to use custom forms. My problem is that my form does not do anything after I submit it.
I am following the documentation here:https://docs.djangoproject.com/en/4.1/topics/forms/
I have the following files:
forms.py:
from django import forms
class TestForm(forms.Form):
text = forms.CharField(label='Text', max_length=50)
urls.py:
from django.urls import path
from . import views
app_name = 'home'
urlpatterns = [
path('', views.index, name='index'),
path('test', views.test_view, name='test')
]
views.py:
def index(request):
return render(request, 'index.html', context)
def test_view(request):
if request.method == 'POST':
form = TestForm(request.POST)
if form.is_valid():
return HttpResponseRedirect('home:index')
else:
form = TestForm()
return render(request, 'test.html', context={'form':form, 'text':'No text yet.',})
template: test.html
<div>
<form action="home:club-invite" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
<hr>
<p>Your text: {{ text }}</p>
</div>
The problem is that the Submit button does nothing. I was expecting a redirect to the index page. But here is no error, no subsequent http request or redirect, nothing...
Am I missing something here?
PS:I also tried return redirect('home:index'). Still no success.
#MODS- Although it has been asked on here before I can not find a suitable answer in Django 3, please read through all I have tried before deleting
Preamble:
I am working through This Tutorial that is taught in Django 1, I am following it but making necessary changes for Django 3.
QUESTION:
I receive an error when loading my page with a form on it.
HTML for the form page:
{% block title %}Start a New Topic{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ board.name }}</li>
<li class="breadcrumb-item active">New topic</li>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Post</button>
</form>
{% endblock %}
Base HTML:
{% block title %}Start a New Topic{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Boards</li>
<li class="breadcrumb-item">{{ board.name }}</li>
<li class="breadcrumb-item active">New topic</li>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Post</button>
</form>
{% endblock %}
urls.py
from django.contrib import admin
from django.urls import path , re_path
#uses path and re_path for regex when needed.
from boards import views
urlpatterns = [
path('admin/', admin.site.urls),
re_path('boards/(?P<pk>\d+)/$', views.board_topics, name='board_topics'),
re_path('boards/(?P<pk>\d+)/new/$', views.new_topic, name='new_topic'),
path('', views.home,name='home'),
]
Forms.py
from .models import Topic
class NewTopicForm(forms.ModelForm):
message = forms.CharField(
widget=forms.Textarea(
attrs={'rows': 5, 'placeholder': 'What is on your mind?'}
),
max_length=4000,
help_text='The max length of the text is 4000.'
)
class Meta:
model = Topic
fields = ['subject', 'message']
views.py
from .models import Board, Topic, Post
from django.contrib.auth.models import User
from .forms import NewTopicForm
from django.http import HttpResponseRedirect
# Create your views here.
def home(request):
boards = Board.objects.all()
return render(request, 'home.html', {'boards': boards})
def board_topics(request, pk):
try:
board = Board.objects.get(pk=pk)
except Board.DoesNotExist:
raise Http404
return render(request, 'topics.html', {'board': board})
def new_topic(request, pk):
board = Board.objects.get(pk=pk)
user = User.objects.first() # TODO: get the currently logged in user
if request.method == 'POST':
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save()
return HttpResponseRedirect('/')
else:
form = NewTopicForm()
return render(request, 'new_topic.html', {'form': form})
I believe my issue is coming from return HttpResponseRedirect('/').
in the tutorial they use a redirect
return redirect('board_topics', pk=board.pk)
However to my knowledge this is not possible in django 3. Also when I looked on the official django 3.1 documentation in forms they use a HttpResponseRedirect aswell.
I have tried using a render but was not able to make it work either.
Any suggestions? I have been stuck on this for a few hours and want to get past it.
Try using reverse:
from django.shortcuts import reverse
... your form ...
return redirect(reverse('board_topics', kwargs={'pk': board.pk}))
btw the regular redirect should also work, try it.
edit
you actually need to pass board as a parameter in your context in your form view:
return render(request, 'new_topic.html', {'form': form, 'board': board})
I've followed the tutorial here to implement a basic search function: https://learndjango.com/tutorials/django-search-tutorial
I'd like to extend that tutorial by making the search function visible on the results page, allowing for repeated search. However, when I do this I can't get the search form to show up on the search results page. The search button shows up, but not the field to provide input.
Relevant code:
home.html:
<div name="searchform">
<form action="{% url 'search_results' %}" method="get">
{{ form }}
<input type="submit" value="Search">
</form>
</div>
{% block content %}
{% endblock %}
search_results.html:
{% extends home.html}
{% block content %}
<h1>Search Results</h1>
<ul>
{% for city in object_list %}
<li>
{{ city.name }}, {{ city.state }}
</li>
{% endfor %}
</ul>
{% endblock %}
Views.py:
from django.db.models import Q
from django.views.generic import TemplateView, ListView, FormView
from .models import City
class HomePageView(FormView):
template_name = 'home.html'
form_class = SearchForm
class SearchResultsView(ListView):
model = City
template_name = 'search_results.html'
def get_queryset(self):
query = self.request.GET.get('q')
object_list = City.objects.filter(
Q(name__icontains=query) | Q(state__icontains=query)
)
return object_list
urls.py:
from django.urls import path
from .views import HomePageView, SearchResultsView
urlpatterns = [
path('search/', SearchResultsView.as_view(), name='search_results'),
path('', HomePageView.as_view(), name='home'),
]
forms.py:
from django import forms
class SearchForm(forms.Form):
q = forms.CharField(label='', max_length=50,
widget=forms.TextInput(attrs={'placeholder': 'Search Here'})
)
Any advice on how I might troubleshoot this sort of issue (or if I'm blatantly doing something un-django-y) would be greatly appreciated.
You're using ListView which is a Generic display view.
You need to use get method, then you can pass the form to make the search again and stay on the same page.
class SearchResultsView(View):
template_name = 'search_results.html'
form_class = SearchForm
def get(self, request):
form = self.form_class()
query = self.request.GET.get('q')
context = {}
context['form'] = form
context['cities'] = City.objects.filter(
Q(name__icontains=query) | Q(state__icontains=query)
)
return render(self.request, self.template_name, context)
You can achieve the same result with ListView but is better if you use other based view class.
You can check the doc. here
class HomePageView(FormView):
template_name = 'home.html'
form_class = SearchForm # This line!
Remember to also apply the form_class attribute to SearchResultsView, otherwise, no forms will be interpreted. The submit button only shows up because it's not a part of the rendered form.
I have been going over a Django tutorial and I have come across an issue where whenever I am trying to post a form to pass data from the webpage to the database it will not go to the method that it is supposed to go to in order for the action to be performed. Here is the code
urls.py
from django.urls import path, re_path
from . import views
app_name = 'music'
urlpatterns = [
path('', views.index, name='index'),
# /music/<album_id>/
re_path('(?P<album_id>[0-9]+)/', views.detail, name='detail'),
# /music/<album_id>/favorite/
re_path('(?P<album_id>[0-9]+)/favorite/', views.favorite, name='favorite'),
]
details.html
<img src="{{ album.album_logo }}"/>
<h1>{{ album.album_title }}</h1>
<h3>{{ album.artist }}</h3>
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form action="{% url 'music:favorite' album.id %}" method="post">
{% csrf_token %}
{% for song in album.song_set.all %}
<input type="radio" id="song{{ forloop.counter }}" name="song" value="song.id"/>
<label for="song{{ forloop.counter }}">
{{ song.song_title }}
{% if song.is_favorite %}
<img src="https://i.imgur.com/b9b13Rd.png"/>
{% endif %}
</label><br>
{% endfor %}
<input type="submit" value="Favorite">
</form>
views.py
from django.shortcuts import render, get_object_or_404
from django.http import Http404
from .models import Album, Song
import pdb;
def index(request):
all_albums = Album.objects.all()
return render(request, 'music/index.html', { 'all_albums': all_albums })
def detail(request, album_id):
album = get_object_or_404(Album, pk=album_id)
return render(request, 'music/detail.html', {'album': album})
def favorite(request, album_id):
album = get_object_or_404(Album, pk=album_id)
try:
selected_song = album.song_set.get(pk=request.POST['song'])
except (KeyError, Song.DoesNotExist):
return render(request, 'music/detail.html', {
'album': album,
'error_message': "You did not select a valid song",
})
selected_song.is_favorite = True
selected_song.save()
return redirect('music:detail', album_id=album_id)
Any pointers would be helpful as to why this is occurring. I went back to the tutorial and I typed whatever was in it again to make sure I did it correctly. It could be because it was a slightly older version I am not sure though. I am running Django version 2.0 while the tutorial was running 1.9.1
The problem is in your favorite view. You have to use an if statement to capture the POST request data. Something like this.
def favorite(request):
if request.method == "POST":
# do whatever you want with your POST data
else:
# do something else
context = {
data: any data that you want to pass to your template
}
return render(request, "your_template.html", context)
See if you can implement a structure like this in your view. If you have any questions or need more details, ask below in comment.
Hope it helps
def favorite(request, album_id):
if request.method == "POST":
album = get_object_or_404(Album, pk=album_id)
try:
selected_song = album.song_set.get(pk=request.POST['song'])
selected_song.is_favorite = True
selected_song.save()
return redirect('music:detail', album_id=album_id)
except (KeyError, Song.DoesNotExist):
return render(request, 'music/detail.html', {
'album': album,
'error_message': "You did not select a valid song",
})
I have overridden my admin change_list.html
{% extends "admin/change_list.html" %}
{% block object-tools-items %}
<li>
Import CSV
</li>
{{ block.super }}
{% endblock %}
When I click this Import CSV link, I would like to import CSV and save to my model.
App's name Auction. Objects of Auction:
forms.py
from django import forms
import csv
from auction.models import AuctionGroup, AuctionHouse, AuctionList
class DataInput(forms.Form):
file = forms.FileField()
def save(self):
records = csv.reader(self.cleaned_data["file"])
for line in records:
house = AuctionHouse()
house.house_name = line[0]
house.auction_type = line[1]
house.auction_day = line[2]
house.volume = line[3]
house.aleado_id = line[4]
house.aleado_photo_number = line[5]
house.house_region = line[6]
house.save()
views.py
def csv_import(request):
if request.method == "POST":
form = DataInput(request.POST, request.FILES)
if form.is_valid():
form.save()
success = True
context = {"form": form, "success": success}
return render_to_response("auction/importcsv.html", context,
context_instance=RequestContext(request))
else:
form = DataInput()
context = {"form": form}
return render_to_response("auction/importcsv.html", context,
context_instance=RequestContext(request))
urls.py
urlpatterns = patterns('',
url(r'/importcsv/$', views.csv_import, name='importcsv'),
)
project/urls.py
urlpatterns = patterns('',
url(r'^auction/', include('auction.urls')),
url(r'^admin/', include(admin.site.urls)),
)
importcsv.html
<!DOCTYPE html>
<html>
<form enctype="multipart/form-data" method="post" action=".">
{{ form }}
</form>
</html>
But it does not work. Please, help. Regards
Use the {% url %} tag in the link code:
Import CSV
If you want to use single template for multiple models then change_list.html has the cl.opts context variable which is a Model._meta of the current model.
So you can pass the app_label and model_name to your importcsv() view:
<a href="{% url 'importcsv' cl.opts.app_label cl.opts.model_name %}"
class="grp-state-focus addlink">Import CSV</a>
Change your urls.py:
urlpatterns = patterns('',
url(r'/importcsv/(\w+)/(\w+)/$', views.csv_import, name='importcsv'),
)
And the signature of the view function:
def csv_import(request, app_label, model_name):
...