Django - Not passing id from template to views - python

In my ToDoApp, I couldn't send the ID to my function. Not sure what mistake I'm making.
Seems my function is correct because when I tested the form action with "datechange/1". It worked.
Here is my code:
Index.html
{% extends 'base.html' %}
{% block content %}
<h3 style = "margin-bottom: 20px"><strong>To Do List App</strong></h3>
<form method="POST" action="datechange/{{task.id}}">
{%csrf_token%}
<ul class="list-group">
{% for task in tasklist %}
<li class="list-group-item d-flex justify-content-between align-items-center">
<input type='hidden' name = {{task.id}}>{{task.tasks}}
<span class="badge bg-primary rounded-pill">{{task.duedate}}
<input type="date" name="datepick"/>
<input type='submit' value = 'Update'>
</span>
</li>
{% endfor %}
</form>
Views.py
def index(request):
tasklist = Task.objects.all()
return render(request, 'index.html', {'tasklist':tasklist})
def datechange(request,id):
# taskid = request.POST.get(id='task.id')
# task = Task.objects.get(id=taskid)
task = Task.objects.get(id=id)
datepick = request.POST.get('datepick')
task.duedate = datepick
task.save()
return HttpResponseRedirect(reverse('index'))
Urls.py
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name='index'),
path('datechange/<int:id>',views.datechange,name='datechange'),
]

Don't use action in form like that, Django has a better behaviour for such simple forms. The view datechange is also not needed. Just put everything from that view into if request.method == "POST" like that:
def index(request):
if request.method == "POST":
task_id = request.POST.get("task_id")
task = Task.objects.get(id=task_id)
datepick = request.POST.get('datepick')
task.duedate = datepick
task.save()
tasklist = Task.objects.all()
return render(request, 'index.html', {'tasklist':tasklist})
And delete action from your form in template:
<form method="POST">
{%csrf_token%}
<input type="hidden" name="task_id" value="{{ task.id }}">
...
Submitting the form will render index again, but also will process everything in POST you have inside that view. If you just open it (GET method) it will ignore that processing opening the view in a standard way.

Related

Reverse for 'list-events' not found

Im currently following a Django tutorial to learn views and URLs. I have watched the tutorial over and over and cant see what I am doing wrong.
I receive the error:
Exception Value:
Reverse for 'list-events' not found. 'list-events' is not a valid view function or pattern name.
Views.py
from django.shortcuts import render, redirect
import calendar
from calendar import HTMLCalendar
from datetime import datetime
from .models import Event, Venue
from .forms import VenueForm, EventForm
from django.http import HttpResponseRedirect
# Create your views here.
# all events is listed in the urls.py hence why the function is named all_events
def update_event(request, event_id):
event = Event.objects.get(pk=event_id)
form = EventForm(request.POST, instance=event)
if form.is_valid():
form.save()
return redirect('list-events')
return render(request, 'events/update_event.html',
{'event': event,
'form':form})
def add_event(request):
submitted = False
if request.method == 'POST':
form = EventForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/add_event?submitted=True')
else:
form = EventForm
if 'submitted' in request.GET:
submitted = True
return render(request, 'events/add_event.html', {'form': form, 'submitted': submitted})
def update_venue(request, venue_id):
venue = Venue.objects.get(pk=venue_id)
form = VenueForm(request.POST, instance=venue)
if form.is_valid():
form.save()
return redirect('list-venues')
return render(request, 'events/update_venue.html',
{'venue': venue,
'form': form})
def search_venues(request):
if request.method == "POST":
searched = request.POST['searched']
venues = Venue.objects.filter(name__contains=searched)
return render(request,
'events/search_venues.html',
{'searched': searched,
'venues': venues})
else:
return render(request,
'events/search_venues.html',
{})
def show_venue(request, venue_id):
venue = Venue.objects.get(pk=venue_id)
return render(request, 'events/show_venue.html',
{'venue': venue})
def list_venues(request):
venue_list = Venue.objects.all()
return render(request, 'events/venue.html',
{'venue_list': venue_list})
URLS.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name="home"),
path('<int:year>/<str:month>/', views.home, name="home"),
path('events', views.all_events, name='list_events'),
path('add_venue', views.add_venue, name='add-venue'),
path('list_venues', views.list_venues, name='list-venues'),
path('show_venue/<venue_id>', views.show_venue, name='show-venue'),
path('search_venues', views.search_venues, name='search-venues'),
path('update_venue/<venue_id>', views.update_venue, name='update-venue'),
path('add_event', views.add_event, name='add-event'),
path('update_event/<event_id>', views.update_event, name='update-event'),
event_list.html:
{% extends 'events/base.html' %}
{% block content %}
<h1>Event </h1>
<br />
{% for event in event_list %}
<div class="card">
<div class="card-header">
{{Event}}
</div>
<div class="card-body">
<h5 class="card-title">Venue: {{ event.venue }}</h5>
<p class="card-text">
<ul>
<li>Date: {{ event.event_date }}</li>
<li>Event Venue: {{ event.venue.web }}</li>
<li>Manager: {{ event.manager }}</li>
<li>Desc: {{ event.description }}</li>
<li>Attendees:<br />
{% for user in event.attendees.all %}
{{ user }}<br/>
{% endfor %}
</li>
</ul>
</p>
</div>
<div class="card-footer text-muted">
Update Event
</div>
</div>
<br /><br />
{% endfor %}
{% endblock %}
You have defined your url in the "urls.py" file with the name of "list_events" (note the underscore). In the views you have used it as "list-events" (note the hyphen).
You can fix that by following one of these options:
1.You can change that in the views (by using underscore instead of hyphen):
return redirect('list_events')
2.Or changing it in the url (by using hyphen instead of underscore):
path('events', views.all_events, name='list-events'),

Django submit file form won't save to models through front-end

So the goal is to get the user to upload images inside the application, and for the images to be displayed on the screen.
The problem is that the forms will not save to the models I made. I am following Django Central https://djangocentral.com/uploading-images-with-django/ for guidance for uploading my images.
What I have at the moment is where the user can type inside the form for their caption and where the user can select a file for their image, but nothing happens when they click the upload button. All that happens, is that it redirects me to the homepage for some reason, but I can fix that later. The only way for the images to be displayed on the website is if I manually go into the admin panel and upload the image there. If anyone could help I would much appreciate it.
view.py
def profile(request):
if request.method == "POST":
form = User_Profile_Form(data = request.POST, files = request.FILES)
if form.is_valid():
form.save()
obj = form.instance
return render(request, "main/profile.html", {"obj":obj})
else:
form = User_Profile_Form()
img = User_Profile.objects.all()
return render(request,"main/profile.html", {"img":img, "form":form})
models.py
class User_Profile(models.Model):
caption = models.CharField(max_length = 100)
image = models.ImageField(upload_to = "img/%y", blank=True)
def __str__(self):
return self.caption
forms.py
from django import forms
from .models import User_Profile
class User_Profile_Form(forms.ModelForm):
class Meta:
model = User_Profile
fields = ("caption", "image")
profile.html
<div class="container">
<form action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn btn-lg btn-success">Upload</button>
</form>
{% if obj %}
<h3>Succesfully uploaded : {{img_obj.caption}}</h3>
<img src="{{ obj.image.url}}" alt="image" class="img-thumbnail" >
{% endif %}
<hr>
{% for x in img %}
{% if forloop.first %}<div class="row ">{% endif %}
<div class="col-lg-4 col-md-4 col-12" >
<div class="text-center mt-2">
<img src="{{x.image.url}}" height="70%" width="70%" class="img-thumbnail" alt="...">
<h2 class="text-center" >{{x.caption}}</h2></div>
</div>
{% if forloop.counter|divisibleby:3 %}
</div>
<div class=row>{% endif %}
{% if forloop.last %}</div>{% endif %}
{% endfor %}
</div>
In the template change the action:
from:
<form action="." method="post" enctype="multipart/form-data">
To:
<form action="" method="post" enctype="multipart/form-data">
. redirects you to the home page.
in views.py
def profile(request):
if request.method == "POST":
form = User_Profile_Form(data = request.POST, files = request.FILES)
if form.is_valid():
form.save()
obj = form.instance
return render(request, "main/profile.html", {"obj":obj, "form":form})
else:
form = User_Profile_Form()
img = User_Profile.objects.all()
return render(request,"main/profile.html", {"img":img, "form":form})
i know what you want to do, i did it on my project, here is my code, edited for your self
views.py
pimageupdate = ProfileImageUpdate(request.POST,request.FILES, instance=request.user.userprofile)
if pimageupdate.is_valid():
pimageupdate.save()
should i note that pimageupdate is getting the form from forms.py
and you should add user in your {{}} code like this
{{user.userprofile.default_profile_picture}}
change "post" in your form tag to "POST"
hope this work, let me know if you tried them

Django Search function

How do I provide a search bar in django? My code is as follows...
home.html
<form method='GET' action="">
<input type="text" name="search" placeholder="Search posts"/>
<input type="submit" value="Search"/>
</form>
views.py
def home(request):
posts = Post.objects.all()
search_term = ''
if 'search' in request.GET:
search_term = request.GET['search']
posts = posts.filter(text__icontains=search_term)
context = {
'posts': posts,
'search-term': search_term
}
return render(request, 'feed/home.html', context)
You likely need a function-based view. This is probably a duplicate or semi-related question.
from django.shortcuts import render
from django.db.models import Q
from .models import Posts #or whatever your model is
def search(request):
query = request.GET.get('q','')
#The empty string handles an empty "request"
if query:
queryset = (Q(text__icontains=query))
#I assume "text" is a field in your model
#i.e., text = model.TextField()
#Use | if searching multiple fields, i.e.,
#queryset = (Q(text__icontains=query))|(Q(other__icontains=query))
results = Posts.objects.filter(queryset).distinct()
else:
results = []
return render(request, 'home.html', {'results':results, 'query':query})
#You can also set context = {'results':results, 'query':query} after
#the else: (same indentation as return statement), and
#use render(request, 'home.html', context) if you prefer.
You should be able come up with your own error-handling or redirects as needed. Your urls.py will probably have to be something like:
from django.urls import path
from . import views
urlpatterns = [
path('feed/', views.search, name='home'),
#'feed/' being the name of desired url, 'views.search' the
#name of your func-based view, and "name='home'" the template
#you're using.
]
And your search bar would prob need to look like:
<form method='GET' action=".">
#I believe lowercase get also works
<input type="text" name="q" placeholder="Search posts"/>
<input type="submit" value="{{ query|escape }}"/>
</form>
EDIT: I forgot that you'll want to access the results and display them in your template (you can drop this in under the form for now). Something like:
{% if query %}
{% if results %}
<ul>
{% for item in results %}
<li>{{ item|escape }}</li>
{% endfor %}
</ul>
{% else %}
<p>Query returned no results.</p>
#SO is formatting "Query" in HTML for some reason. Nonetheless...
{% endif %}
{% endif %}

Django form not rendering properly

I am following the documentation of the Django Forms but I do not know why my form does not want to show up !
I am creating a form that will get an email en create invitation for user to sign in using this app :https://github.com/bee-keeper/django-invitations
My forms.py:
class InviteForm(forms.Form):
email1 = forms.EmailField(label='Email 1')
My Views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import InviteForm
class candidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
def create_invite(request):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid:
email = form.cleaned_data['email1']
invite = Invitation.create('form.email1')
invite.send_invitation(request)
print("The mail was went")
else:
print("Your form is not valid")
else:
form = InviteForm()
return render(request, 'HRindex.html', {'form': form})
My HTML:
{% extends 'base.html' %}
{% block body %}
<div class="jumbotron">
<h1>Welcome to SoftScores.com</h1>
<h2>Team analytics platfom</h2>
<h3>Welcome to {{user.username}}, it is your Page</h3>
</div>
<div class="container">
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Create a new team
</a>
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
In order to create a new team please invite new members. A link will be sent to them in order to give the access to the application
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
urls.py:
from django.conf.urls import url
from website import views
app_name = 'website'
urlpatterns = [
url(r'^candidateIndex/$', views.candidateIndex.as_view(), name='candidate_index'),
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
]
When it render the page I get only the button but the form does not seems to work
Do you habe any idea ?
You HR_index url is being handled by the HRIndex view, but this does not have any code to handle the form.
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
Since a TemplateView is not really suited to handling a form, it would be better to modify the URL pattern to use the create_invite view instead:
url(r'^HRIndex/$', views.create_invite, name='HR_index'),

Field value not turning up in request.POST querydict - python django

I'm sure I'm doing something really obviously wrong, but I can't see it.
I've made a simple form for a Django app, but it's only returning the csrf token, not the field value. The form submits fine, but there's no 'event-title' key/value pair in the QueryDict.
To be precise, when I log the QueryDict, it looks like this:
<QueryDict: {u'csrfmiddlewaretoken': [u'dpXmMHTE3WmQvdvrAUD4oFer2WfKEjWd']}>
create_event.html:
{% extends "basic-layout.html" %}
{% block maincontent %}
<h1>Create Event</h1>
{% if error_message %}<p>{{ error_message }}</p>{% endif %}
<form action="/create-event" method="post">{% csrf_token %}
<label for="event-title">Event title</label>
<input type="text" title="event-title" id="event-title" required/>
<input type="submit" value="create event"/>
</form>
{% endblock %}
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from django.views.decorators.csrf import csrf_exempt
import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$', views.listEvents),
url(r'^create-event', csrf_exempt(views.createEvent))
]
views.py
def createEvent(request):
if request.method == 'GET':
template = loader.get_template('create_event.html')
context = RequestContext(request, {})
return HttpResponse(template.render(context))
if request.method == 'POST':
logger = logging.getLogger('degub')
logger.info(request.POST)
event_title = request.POST.get('event-title', '')
if event_title:
event = Event(event_title)
c = {}
c.update(csrf(request))
template = loader.get_template('list_events.html')
context = RequestContext(request, c)
return HttpResponse(template.render(context))
else:
template = loader.get_template('create_event.html')
template_values = {"error_message": "Nope, didn't work"}
context = RequestContext(request, template_values)
return HttpResponse(template.render(context))
Try adding the name attribute in your input tag.
<input type="text" name="event-title" title="event-title" id="event-title" required/>

Categories