How do I link two views to one template file in Django - python

I'm trying to build a very basic messaging app where someone types into a text input, presses send then see's the message on the screen. And I want to do all of this on the same URL. Here is what I have right now:
views.py:
from django.shortcuts import render
from django.views.generic import ListView, CreateView
from message import models
# Create your views here.
class ViewMessages(ListView):
model = models.Messages
context_object_name = 'messages'
class WriteMessages(CreateView):
fields = ('message',)
model = models.Messages
models.py:
from django.db import models
from django import forms
from django.core.urlresolvers import reverse
# Create your models here.
class Messages(models.Model):
message = models.CharField(max_length=300)
def __str__(self):
return self.message
def get_absolute_url(self):
return reverse("view")
project urls.py:
from django.conf.urls import url
from django.contrib import admin
from message import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^view/', views.ViewMessages.as_view(), name="view"),
url(r'^create/', views.WriteMessages.as_view(), name="create"),
]
messages_form.html
{% extends "message/base.html" %}
{% block head_block %}
<title>Create Message</title>
{% endblock %}
{% block body_block %}
{% for message in messages %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<form method="POST" class="form-horizontal">
{% csrf_token %}
<div class="text-center" style="position: fixed; top: 500px;">
<span style="margin: 10px;">{{ form }}</span>
<br>
<input type="submit" value="Send" class="btn btn-primary btn-group btn-group-lg" >
</div>
</form>
{% endblock %}
messages_list.html:
<!DOCTYPE html>
{% extends "message/base.html" %}
{% block head_block %}
<title>Read Messages</title>
{% endblock %}
{% block body_block %}
<div class="">
{% for message in messages %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<br>
<p><div class="text-center"><a style="border: 1px solid gray;" class="btn btn-success" href="{% url 'create' %}">Write Message</a></div></p>
</div>
{% endblock %}
The basic idea is that I want to combine the "messages_form.html" and "messages_list.html" into one template file called "message.html".
Can anyone help me?

I had something similar and here was my approach
views.py
from django.views import View
class MessageView(View):
template_name = 'message.html'
queryset = Messages.objects.all()
def get_queryset(self):
return self.queryset
def get(self, request, *args, **kwargs):
form = MessageForm()
context = {
'object_list': self.get_queryset(),
"form": form
}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form = MessageForm(request.POST)
if form.is_valid():
form.save()
form = MessageForm()
return redirect('/message')
context = {
'object_list': self.get_queryset(),
"form": form
}
return render(request, self.template_name, context)
message.html
{% extends "message/base.html" %}
{% block head_block %}
<title>Message</title>
{% endblock %}
{% block body_block %}
{% for message in object_list %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<form method="POST" class="form-horizontal">
{% csrf_token %}
<div class="text-center" style="position: fixed; top: 500px;">
<span style="margin: 10px;">{{ form }}</span>
<br>
<input type="submit" value="Send" class="btn btn-primary btn-group btn-group-lg" >
</div>
</form>
{% endblock %}
Display your view in a url
urls.py
from django.urls import path
from .views import MessageView
urlpatterns = [
path('message', MessageView.as_view(), name='messages'),
]

Related

The 'header_image' attribute has no file associated with it

When I create a new post with an image, everything is fine, but if I edit it, I want to delete the image using the "clear" button, then this error appears, and if I change, then nothing changes, but there are no errors
here is models.py
`
from django.db import models
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = models.TextField()
header_image = models.ImageField(blank=True, null=True, upload_to="images/", default='#') #new
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[str(self.id)])`
here is views.py
`
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Post
class BlogListView(ListView):
model = Post
template_name = 'home.html'
class BlogDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class BlogCreateView(CreateView):
model = Post
template_name = 'post_new.html'
fields = ['title', 'author', 'body', 'header_image']
class BlogUpdateView(UpdateView):
model = Post
template_name = 'post_edit.html'
fields = ['title', 'body', 'header_image']
class BlogDeleteView(DeleteView):
model = Post
template_name = 'post_delete.html'
success_url = reverse_lazy('home')
#property
def image_url(self):
"""
Return self.photo.url if self.photo is not None,
'url' exist and has a value, else, return None.
"""
if self.image:
return getattr(self.photo, 'url', None)
return None`
post_base.html
`{% load static %}
<html>
<head>
<title>Django blog</title>
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400"
rel="stylesheet">
<link href="{% static 'css/base.css' %}" rel="stylesheet">
</head>
<body>
<div>
<header>
<div class="nav-left">
<h1>Django blog</h1>
<h2>Admin</h2>
</div>
<div class="nav-right">
+ New Blog Post
</div>
</header>
{% if user.is_authenticated %}
<p>Hi {{ user.username }}!</p>
{% else %}
<p>You are not logged in.</p>
Log In<br>
<p>Sign up</p>
{% endif %}
{% block content %}
{% endblock content %}
</div>
</body>
</html>`
post_detail.html
`
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
<p>+ Edit Blog Post</p>
<p>+ Delete Blog Post</p>
<img src="{{ post.header_image.url|default_if_none:'#' }}">
{{ post.body|safe }}
{% endblock content %}`
post_new.html
`
{% extends 'base.html' %}
{% block content %}
<h1>New post</h1>
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
{% endblock content %}`
post_edit.html
`
{% extends 'base.html' %}
{% block content %}
<h1>Edit post</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update" />
</form>
{% endblock content %}`
enctype='multipart/form-data' means that no characters will be encoded. that is why this type is used while uploading files to server. So multipart/form-data is used when a form requires binary data, like the contents of a file, to be uploaded.
You forgot to add enctype='multipart/form-data' in your post_edit.html form and that's the reason your files aren't sent to Django. Following code should work.
post_edit.html
{% extends 'base.html' %}
{% block content %}
<h1>Edit post</h1>
<form action="" method="post" enctype='multipart/form-data'>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update" />
</form>
{% endblock content %}

How to Display/Fetch Data on button click using AJAX in Python - AJAX

I am new to both ajax and django. I want to fetch phone number from database and want to display on template when click user the contact button. But in my case I am getting all the phone numbers in first button itself which is not correct. Because different persons have different phone numbers. Please help me. Thanks in advance.
views.py:
from django.shortcuts import render, redirect
from .models import listing_model
from .forms import listing_form
from django.http import HttpResponse
def submissions(request):
tasks = listing_model.objects.all()
form = listing_form()
if request.method =='POST':
form = listing_form(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('submissions')
context = {'tasks':tasks, 'form':form}
return render(request, 'submission.html', context)
#ajax
def contact(request):
numbers= listing_model.objects.values('phone')
return HttpResponse( numbers )
home.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Home{% endblock %}
{% block body %}
<div class="container">
<div class="row">
<form method="GET" class="mx-auto" ><br>
{{ user_filter.form }}<br><br>
<button type="submit" class="btn btn-info" style="margin-left:250px">Search</button>
</form>
</div>
</div>
<div> </div>
<div class="container">
<div class="row">
{% for task in tasks %}
<div class ="col-md-4">
<div class="card" style="width:300px">
<div class="card-body">
<h4 class="card-title">Title : {{ task.title }}</h4>
<div>Address : {{ task.address }}</div>
<div>City : {{ task.city }}</div>
<img src="{{ task.image.url }}" style="max-height:200px">
<div> </div>
<button class="btn btn-primary" id="request-btn">Contact</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#request-btn").click(function(e){
e.preventDefault();
$.ajax({
url: "/listings/contact",
type: "GET",
datatype:"json",
success: function(numbers){
alert(numbers)
}
});
});
});
</script>
</div>
</div></div>
{% endfor %}
</div></div>
{% endblock %}
urls.py
from django.contrib import admin
from django.urls import path
from ajax_with_djnago import views
urlpatterns = [
path('admin/', admin.site.urls),
path('listings/contact/<str:id>', views.contact),
path('', views.home)
]
views.py
from django.shortcuts import render
from .models import listing_model
from django.http import JsonResponse
def home(request):
all_detail = listing_model.objects.all()
print(all_detail)
return render(request, 'index.html', context={'tasks': all_detail})
# ajax
def contact(request, id):
numbers = listing_model.objects.get(id=id)
return JsonResponse({'numbers': numbers.phone}
)
models.py
from django.db import models
# Create your models here.
class listing_model(models.Model):
title = models.CharField(max_length=200, blank=True)
address = models.CharField(max_length=200)
city = models.CharField(max_length=200)
image = models.ImageField(upload_to='images', blank=True)
phone = models.IntegerField()
def __str__(self):
return self.title
index.html
<div class="container">
<div class="row">
{% for task in tasks %}
<div class="col-md-4">
<div class="card" style="width:300px">
<div class="card-body">
{% for task in tasks %}
<h4 class="card-title">Title : {{ task.title }}</h4>
<div>Address : {{ task.address }}</div>
<div>City : {{ task.city }}</div>
<div> </div>
<button class="btn btn-primary"
id={{ task.id }} onclick="showPopup('{{ task.id }}')">Contact
</button>
<p id="contact"></p>
{% endfor %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
function showPopup(id) {
$.ajax({
url: "/listings/contact/" + id,
method: 'GET',
headers: {'X-CSRFToken': '{{ csrf_token }}'},
success: function (data) {
$('#contact').html(data['numbers']);
}
});
}
</script>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
For Complete Code Please check this link

Problem in creating delete button in django

I am trying to build delete button and currently stuck. I am new to django and need help. Thank You
This is my models.py:-
from django.db import models
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
# Create your models here.
class simpleList(models.Model):
title = models.CharField(max_length=250)
def __str__(self):
return self.title
This is my views.py:-
from django.shortcuts import render, get_object_or_404
from .models import simpleList
from django.views.generic import ListView, DeleteView
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
# Create your views here.
class ListListView(ListView):
model = simpleList
template_name = 'list_list.html'
class DeleteList(SuccessMessageMixin, DeleteView):
model = simpleList
success_url = '/'
success_message = "deleted..."
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
name = self.object.title
# name will be change according to your need
request.session['title'] = title
message = request.session['title'] + ' deleted successfully'
messages.success(self.request, message)
return super(DeleteView, self).delete(request, *args, **kwargs)
This is my urls.py:-
from django.urls import path
from .views import ListListView, DeleteList
from django.conf.urls import url
from . import views
urlpatterns = [
path('', ListListView.as_view(), name='list_list'),
path('<int:pk>/', DeleteList.as_view(), name='delete_view'),
]
This is my home.html:-
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<div>
{% if user.is_authenticated %}
<button type="button" class="btn btn-info"><a style="color: white;" href="{% url 'list_list' %}">Continue to
slist</a></button>
{% endif %}
</div>
{% endblock content %}
and this is my list_list.html which is currently not complete:-
{% extends 'base.html' %}
{% block title %}sList{% endblock title %}
{% block content %}
<h2>simpleList</h2>
{% for simpleList in object_list %}
<div>
<h3>{{ simpleList.title }}</h3>
<div>
<form action="{% url 'delete_view' pk=part.pk %}">{% csrf_token %}
X<input class="btn btn-default btn-danger" type="submit" value="Delete" />
</form>
</div>
</div>
{% endfor %}
{% endblock content %}
The error i am getting from django is this:-
NoReverseMatch at /list/
Reverse for 'delete_view' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['list/(?P[0-9]+)/$']
10 <body>
11 <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
12 <a class="navbar-brand" href="{% url 'home' %}">simpleList</a>
13 <div class="collapse navbar-collapse" id="navbarColor01"></div>
14 {% if user.is_authenticated %}
15 <button type="button" class="btn btn-secondary">Hi, {{ user.username }}</button>
16 <button type="button" class="btn btn-info"><a style="color:white;" href="{% url 'logout' %}">Logout</a></button>
You need to make a POST request to delete the object. Furthermore the name of the object is simpleList, not part, so the form should be rewritten to:
<form method="post" action="{% url 'delete_view' pk=simpleList.pk %}">
{% csrf_token %}
<input class="btn btn-default btn-danger" type="submit" value="Delete" />
</form>
While it is not a problem to use <int:pk>/ as the path pattern. It might be better to use <int:pk>/delete, for example, since <int:pk>/ is often used to show the details of the object with that primary key:
urlpatterns = [
path('', ListListView.as_view(), name='list_list'),
path('<int:pk>/delete/', DeleteList.as_view(), name='delete_view'),
]

Django - Render view based on search query from search view

I have what is probably a very basic question. I have read through Django forms docs but am still missing something here. I want to have a search bar in one template (search.html) and return the search query in another template (results.html). I have the following so far, using this SO answer as a guide, which returns the following error. Thanks for any help.
Exception Value:
results() missing 1 required positional argument: 'search_id'
urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^landing/', views.search, name='search'),
url(r'^results/', views.results, name='results'),
]
forms.py
from .models import Apartment
class Apt(forms.ModelForm):
class Meta:
model = Apartment
fields = ('name')
views.py
def search(request):
if request.method == 'POST': #the form has been submitted
form = Apt(request.POST) #bound form
if form.is_valid(): #validations have passed
name = form.cleaned_data['name']
u = Apt.objects.create(name=name)
#REST query will go here.
#commit to database
u.save()
return redirect('results', search_id=u.name)
else: #create an unbound instance of the form
form = Apt(initial={'name':'name'})
#render the form according to the template, context = form
return render(request, 'search/landing.html', {'form':form})
def results(request, search_id):
search_id = request.POST.get('name')
query = get_object_or_404(Apt, pk=search_id)
return render(request, 'search/results.html', {'query':query} )
landing.html
{% extends "base_simple.html" %}
{% block title %}Look up your name{% endblock %}
{% block main_content %}
<!-- Intro Header -->
<header class="intro">
<div class="intro-body">
<div class="container">
<div class="inner cover">
<h1 class="cover-heading">find your name</h1>
<form id="searchform" method="POST" action="" accept-charset="utf-8">
{% csrf_token %}
<input id="apt" type="text" class="form-control" placeholder="Apartment Name" value="{{ Apt.name }}">
<input type="submit" value="Search" class="btn btn-lg btn-default">
</form>
</div>
</div>
</div>
</header>
{% endblock %}
results.html
{% extends "base_simple.html" %}
{% block title %}search results{% endblock %}
{% block main_content %}
<div class='col-sm-6 col-sm-offset-3'>
<div class="row">
<div class="col-sm-12">
{% for q in query %}
<div class="jumbotron">
<h3>{{ q.name }}</h3>
</div>
{% endfor %}
</div>
</div>
<hr/>
</div>
{% endblock %}
in urls you need to change result to
url(r'^results/(?P<search_id>.+)/', views.results, name='results'),
Named groups in the regex are passed as arguments to the view
You should also remove the line search_id = request.POST.get('name') from your results view as the redirect will not contain any POST data

BootstrapError Parameter "form" should contain a valid Django Form

i have an app called reviews
reviews/forms.py
from django.forms import ModelForm, Textarea
from reviews.models import Review
class ReviewForm(ModelForm):
class Meta:
model = Review
fields = ['rating', 'comment']
widgets = {
'comment': Textarea(attrs={'cols': 40, 'rows': 15}),
}
reviews/views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .models import Review, Wine
from .forms import ReviewForm
import datetime
from django.contrib.auth.decorators import login_required
#login_required
def add_review(request, wine_id):
wine = get_object_or_404(Wine, pk=wine_id)
form = ReviewForm(request.POST)
if form.is_valid():
rating = form.cleaned_data['rating']
comment = form.cleaned_data['comment']
user_name = form.cleaned_data['user_name']
user_name = request.user.username
review = Review()
review.wine = wine
review.user_name = user_name
review.rating = rating
review.comment = comment
review.pub_date = datetime.datetime.now()
review.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,)))
return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})
reviews/templates/reviews/wine_detail.html
{% extends 'base.html' %}
{% load bootstrap3 %}
{% block title %}
<h2>{{ wine.name }}</h2>
<h5>{{ wine.review_set.count }} reviews ({{ wine.average_rating | floatformat }} average rating)</h5>
{% endblock %}
{% block content %}
<h3>Recent reviews</h3>
{% if wine.review_set.all %}
<div class="row">
{% for review in wine.review_set.all %}
<div class="col-xs-6 col-lg-4">
<em>{{ review.comment }}</em>
<h6>Rated {{ review.rating }} of 5 by {{ review.user_name }}</h6>
<h5><a href="{% url 'reviews:review_detail' review.id %}">
Read more
</a></h5>
</div>
{% endfor %}
</div>
{% else %}
<p>No reviews for this wine yet</p>
{% endif %}
<h3>Add your review</h3>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'reviews:add_review' wine.id %}" method="post" class="form">
{% csrf_token %}
{% bootstrap_form form layout='inline' %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "star" %} Add
</button>
{% endbuttons %}
</form>
{% endblock %}
base.html
{% load bootstrap3 %}
{% bootstrap_css %}
{% bootstrap_javascript %}
{% block bootstrap3_content %}
<div class="container">
<nav class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'reviews:review_list' %}">Winerama</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Wine list</li>
<li>Home</li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li>Hello {{ user.username }}</li>
<li>Logout</li>
{% else %}
<li>Login</li>
<li>Register</li>
{% endif %}
</ul>
</div>
</nav>
<h1>{% block title %}(no title){% endblock %}</h1>
{% bootstrap_messages %}
{% block content %}(no content){% endblock %}
</div>
{% endblock %}
I am getting the error at the line {% bootstrap_form form layout='inline' %} in the html file
Any idea how to fix this?
There's a few problems with your code as it stands, so I'll try to clean it up with some comments as I would write it to add a review to a wine.
#login_required
def add_review(request, wine_id):
wine = get_object_or_404(Wine, pk=wine_id)
if request.POST:
form = ReviewForm(request.POST)
else:
form = ReviewForm()
if form.is_valid():
### NO NEED FOR - already set as part of valid modelform ::: rating = form.cleaned_data['rating']
### AS WELL AS ::: comment = form.cleaned_data['comment']
### THIS IS NOT A FIELD IN YOUR FORM :::user_name = form.cleaned_data['user_name']
user_name = request.user.username
review = form.save(commit=False) # commit = False means that this instantiate but not save a Review model object
review.wine = wine
review.user_name = user_name # Why use this instead of a ForeignKey to user?
review.pub_date = datetime.datetime.now() # works as long as pub_date is a DateTimeField
review.save() # save to the DB now
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,))) # THIS will redirect only upon form save
return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})
Now, the error your seeing is most likely related to you passing request.POST to a form even if request.POST is blank; the form will attempt to set initial values but with a querydict that has no values that actually relates to the form.
EDIT: In response to your comments, my next step would be to try and render each form field individually and see if I can trigger a failure.
Instead of {% bootstrap_form form layout='inline' %}, try-
{% for field in form %}
{% bootstrap_field field %}
{% endfor %}
If this is an error with the django-bootstrap library trying to render the textarea widget and the inline style together (as I would suspect at this point), you can also eliminate the widget parameter and see if there's a fix. If there is, I'd suggest overriding your modelform's init method for assign a widget post a call super on init.
In Class Base View
This error may occur when you use form_class in the wrong generic view.
⮕ Open your views.py then check to see if you have set the wrong generic view in your class.
Example
class ProfileUpdateView(T̶e̶m̶p̶l̶a̶t̶e̶V̶i̶e̶w̶ UpdateView):
model = User
form_class = forms.ProfileForm
success_url = reverse_lazy("stories:story_list")
template_name = 'profile.html'
def get_object(self, queryset=None):
return get_object_or_404(User, pk=self.request.user.id)

Categories

Resources