I wanted to create a website where I can List all created forms and also create forms in the same page. But I could'n figure it out. Firstly I tried it with two classes which linked to the same HTML file but then I read that this is wrong then I tried to write the two classes in one with the get post and get_queryset functions. However now I can only create forms and if I am deleting the get function the I can list the created forms.
Thank You very much and here are my views.py and HTML.
views.py
from django.shortcuts import render,redirect
from django.contrib.auth.decorators import login_required
from django.views import generic
from .models import PostModel
from .forms import PostForm
# Create your views here.
class PostList(generic.ListView):
template_name = 'home.html'
form_class=PostForm
def get_queryset(self):
return PostModel.objects.order_by('-created_on')
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self,request,*args, **kwargs):
form=self.form_class(request.POST)
if form.is_valid():
form.save()
return redirect('home')
return render(request,self.template_name,{'form':form})
class PostDetail(generic.DetailView):
model = PostModel
template_name = 'post_detail.html'
home.html
{% extends "base.html" %}
{%block content%}
<div class="container">
<div class="row">
<!-- Blog Entries Column -->
<div class="col-md-6 mt-3 left mx-auto">
{% for post in postmodel_list %}
<div class="card mb-4 block">
<a class="overlay" href="{% url 'post_detail' post.slug %}"style="text-decoration:none"> </a>
<div class="card-body inner">
<p style="text-align:right;float:right;margin-top:10px;" class="card-text text-muted h6"><a style="text-decoration:none" href="https://google.com">#{{ post.author }}</a> </p>
<h2 class="card-title">{{ post.title }}</h2>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="col-md-4 float-right ">
<button style= "position: fixed; bottom:50px;" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="#mdo">Open modal for #mdo</button>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New message</h5>
</div>
<div class="modal-body">
<form method="post" style="margin-top: 1.3em;">
{% csrf_token %}
{{ form }}
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
<style>
.card{
box-shadow: 0 16px 48px #E3E7EB;
}
</style>
{%endblock content%}
If I understand the question properly you can use CreateView instead of ListView and return the post lists in the context from get_context_data.
class PostList(generic.CreateView):
template_name = 'home.html'
form_class=PostForm
model = Post
def get_context_data(self, **kwargs)
context = super().get_context_data(**kwargs)
context ['postmodel_list'] = PostModel.objects.order_by('-created_on')
return context
Related
I've got empty Bootstrap modal form with Django UpdateView(CBV)
The most important question without using js , I will not be able to display data in a modal window? (I only use bootstrap.bundle.min.js in base.html)
Modal window show fields of empty form
view.py
class HistoryPamentsByService(ListView):
model=Payments
form_class=PaymentsForm
template_name ='myflat/history_by_service.html'
context_object_name='flats'
slug_url_kwarg = 'slug'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
form=PaymentsForm()
payments=Payments.objects.filter(flats_id=self.kwargs['flats_id'])
context['form']=form
return context
def get_form(self,*args,**kwargs):
super().get_form(*args, **kwargs)
form=PaymentsForm()
return form
def get_queryset(self):
return Payments.objects.filter(slug=self.kwargs['slug'],flats_id=self.kwargs['flats_id'])
class UpdatePayments(UpdateView):
model=Payments
pk_url_kwarg='pk'
template_name='myflat/update_modal.html'
context_object_name='name_flat'
fields=['name_service','amount_of_bill',
'amount_of_real',
'date_of_bill',
'date_of_payment',
'status_payment',
'comments',
'bill_save_pdf']
def get_success_url(self):
return reverse('HistoryPamentsByService',
kwargs={'slug':self.object.slug,
'flats_id': self.object.flats_id})
urls.py
urlpatterns = [ path('history_by_service/<slug:slug>/<int:flats_id>/',
HistoryPamentsByService.as_view(),name='HistoryPamentsByService'),
path('UpdatePayments/<int:pk>/',UpdatePayments.as_view(),name='UpdatePayments'),
]
template
history_by_service.html (for ListView)
{%extends "base.html"%}
{%block content%}
{% for flat in flats %}
<tr>
<td scope="row">{{ forloop.counter }} </td>
<td>{{flat.name_service}}</td>
<td>{{flat.amount_of_bill}}</td>
<td>{{flat.amount_of_real}}</td>
<td>{{flat.date_of_bill}}</td>
<td>{{flat.date_of_payment}}</td>
<td>{{flat.get_status_payment_display}}</td>
<td>{{flat.comments}}</td>
<td>{{flat.bill_save_pdf}}</td>
<td>
<form method="post" action="{% url 'UpdatePayments' flat.pk %}" enctype="multipart/form-data">
{% csrf_token %}
<button type='button' class='btn btn-success btn-sm' id="update_modal"
data-bs-toggle="modal" data-bs-target="#update_modal{{flat.pk}}">
<i class="fa-regular fa-pen-to-square fa-fw"></i>Edit</button>
{% include "myflat/update_modal.html" %}
</form>
{% endfor %}
{% endblock content %}
template
update_modal.html
<div class="modal fade" id="update_modal{{flat.pk}}" data-bs-backdrop="static"
data-bs-keyboard="false" tabindex="-1" aria-labelledby="update_modal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content" style="width:auto">
<div class="modal-header">
<h5 class="modal-title " id="update_modalLabel">{{flat.name_flat}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="post" action="{% url 'UpdatePayments' flat.pk %}" enctype="multipart/form-data">
<div class="modal-body">
{% csrf_token %}
{% for field in form %}
{{field}}
{% endfor %}
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" >
<i class="fa-solid fa-trash fa-fw" ></i>Save</button>
<button type="button" class="btn btn-warning"
data-bs-dismiss="modal">
<i class="fa-regular fa-circle-xmark"></i>Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
I try add in UpdatePayments(UpdateView) next code:
class UpdatePayments(UpdateView):
model=Payments
pk_url_kwarg='pk'
form_class=PaymentsForm
template_name='myflat/update_modal.html'
context_object_name='name_flat'
def get_context_data(self, **kwargs):
context= super().get_context_data(**kwargs)
obj=Payments.objects.get(pk=self.kwargs['pk'])
form=PaymentsForm(self.request.POST or None ,instance=obj)
context['form']=form
return context
but still nothing in Modal is empty fields!!!
What's wrong, any helps,please!!!
Problem
I'm trying to transfer my current form on a new page to a Modal window that appears on the current page but I can't get the form fields to appear.
I have thoughts that it may be due to my urls or the view that worked previously doesn't work with a Modal pop-up.
Views
class AssetView(TemplateView):
template_name = 'coinprices/my-dashboard.html'
def get(self, request, **kwargs):
form_a = AssetForm(prefix='form_a')
return render(request, self.template_name, {
'form_a': form_a
})
def post(self, request):
form_a = AssetForm(request.POST, prefix='form_a')
if form_a.is_valid():
post = form_a.save(commit=False)
post.user = request.user
post.save()
return redirect('dashboard')
args = {
'form_a': form_a
}
return render(request, self.template_name, args)
HTML
<!-- Button trigger modal -->
<button type="button" class="btn btn-outline-success btn-sm" data-bs-toggle="modal" data-bs-target="#exampleModal">
Add Asset
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post">
{% csrf_token %}
{{ form_a.as_p }}
<button class="btn btn-outline-success btn-sm">Confirm</button>
</form>
<a href="/coinprices/my-dashboard">
<button class="btn btn btn-outline-dark btn-sm">Dashboard</button>
</a>
</div>
</div>
</div>
</div>
URLS
urlpatterns = [
path('my-dashboard/', get_asset_price, name='dashboard'),
path('my-dashboard/', AssetView.as_view(template_name='coinprices/my-dashboard.html'), name='asset'),
]
Is there a way I can combine a detailview and a form into the same view? I'm making a rental system where when a user clicks on a particular house, he will be directed to a detailview page of that house. And after viewing the details of the house he intends to rent, he will fill a form while still on the detailview page then the form will be saved in the database.
Here's what I have so far
views.py
class HouseDetailView(DetailView):
model = House
template_name = 'Home/detail.html'
def get_context_data(self, **kwargs):
context = super(HouseDetailView, self).get_context_data(**kwargs)
context['house_list'] = House.objects.all()
return context
def Callback (request):
form = CallbackForm()
if request.method == 'POST':
form = CallbackForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Callback Submission Successful.')
return redirect('Home')
context = {'form':form}
return render(request, 'Home/callback.html', context)
urls.py
from django.urls import path
from .views import (
HouseView,
HouseDetailView,
)
from . import views
urlpatterns = [
path('Home/', views.Home, name='Home'),
path('SignUp/', views.SignUp, name='SignUp'),
path('Login/', views.Login, name='Login'),
path('house/', HouseView.as_view(), name='house'),
path('callback/', views.Callback, name='callback'),
path('Logout/', views.Login, name='Logout'),
path('<slug:slug>/', HouseDetailView.as_view(), name='detail'),
]
forms.py
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
from .models import House, Lease, Agent, Customer, Callback
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class CallbackForm(ModelForm):
class Meta:
model = Callback
fields = ['Username', 'Phone', 'email', 'HouseId']
Templates
lease.html
{% extends "Home/Base.html" %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-lg-6">
<div class="box-element1">
<form method="POST" action="">
<div id="user-info">
<div class="d-flex justify-content-center">
<h3 id="form-title">Personal Details</h3>
</div>
{% csrf_token %}
<div class="input-group mb-2">
<span class="input-group-text"><i class="fas fa-user"></i></span>
<input type="text" class="form-control" name="Username" >
</div>
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-phone-square"></i></span>
</div>
<input type="text" class="form-control" name="Phone" >
</div>
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-envelope-square"></i>
</span>
</div>
<input type="email" class="form-control" name="email" >
</div>
<div class="input-group mb-2">
<div class="input-group-append">
<span class="input-group-text"><i class="fas fa-home"></i></span>
</div>
<input type="HouseId" class="form-control" name="HouseId" >
</div>
<div class="d-flex justify-content-center mt-3">
<input id="form-button" class="btn btn-success btn-block" type="submit"
name="Lease" value="Get a Call Back">
</div>
</div>
</form>
{{form.errors}}
<script>
var form_fields = document.getElementsByTagName('input')
form_fields[1].placeholder='Username..';
form_fields[2].placeholder='Phone..';
form_fields[3].placeholder='email..';
form_fields[4].placeholder='HouseId..';
for (var field in form_fields){
form_fields[field].className += ' form-control'
}
</script>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
<br>
<div class="box-element hidden" id="payment-info">
<small>Paypal Options</small>
</div>
</div>
<div class="col-lg-5">
<div class="card mb-4 shadow-sm">
<img class="thumbnail" src="{{house.image.url}}">
<div class="box-element-house">
<h6><strong> {{house.HouseId}}</strong></h6>
<h6><strong>Type: {{house.HouseType}}</strong></h6>
<h6><strong>Location: {{house.Location}}</strong></h6>
<h6><strong>Status: {{house.Status}}</strong></h6>
<h6><strong>Rent: Ksh.{{house.Rent|floatformat:2}}</strong></h6>
<a btn-outline-success ></a>
</div>
</div>
</div>
</div>
{% endblock content %}
The image below is how the page is supposed to look like
https://drive.google.com/file/d/1gTy2awJU2GCZYhCHauhOgB5DIPQaTLYw/view?usp=sharing
Thanks in advance.
To add any additional context (like form) to your view just override get_context_data method on DetailView and add it to your template's context
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['callback_form'] = CallBackForm(initial={'HouseId': self.object.id})
return context
then you should of course display it somehow on your page in a
<form method='post' action={% url 'your-callback-from-handling-url' %}>
{{ callback_form.as_p }}
<button type='submit'...>...</button>
</form>
and from then you can use another django's built-in View - CreateView which will under the 'your-callback-from-handling-url' url
class CallBackCreateView(CreateView):
model = CallBack
fields = ['Username', 'Phone', 'email', 'HouseId']
success_url = 'url-to-redirect-after-creating-the-CallBack'
This will automatically create your CallBack instance - of course this needs some polishing like error handling and so on. Please read the docs here
I have a question. I have a blog where users can log in and post or comment something. When they are posting or commenting the text appears with their name as links on the right side(see picture). Now I want to have a userprofile page where the email name etc. are displayed. So I have to grab the name from the first template and use it. Now I can grab their name :) but I don't know how to use them. For example the users name is alex. I can display alex on the new template but what I need is something like that. alex.email or alex.name. Thank you very much.
view.py
#login_required
def user_profile(request,username):
return render(request, "user_profile.html",{'username':username})
home.html this is the template where I want to grab his name
{% extends "base.html" %}
{%block content%}
{% load crispy_forms_tags %}
<div class="container">
<div class="row">
<!-- Blog Entries Column -->
<div class="col-md-8 mt-3 left mx-auto">
{% for posts in postmodel_list %}
<div class="card mb-4 block">
<a class="overlay" href="{% url 'post_detail' posts.slug %}"style="text-decoration:none"> </a>
<div class="card-body inner">
<h2 class="card-title">{{ posts.post }}</h2>
<p style="text-align:right;" class="card-text text-muted h6"><a style="text-decoration:none" href="{%url 'user_profile' posts.author %}">#{{ posts.author }}</a> </p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="col-md-4 float-right ">
<button style= "position: fixed; bottom:50px;" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal" data-whatever="#mdo">Add New Post</button>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">New Post</h5>
</div>
<div class="modal-body">
<form method="post" style="margin-top: 1.3em;">
{% csrf_token %}
{{ form|crispy }}
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
<style>
.card{
box-shadow: 0 16px 48px #E3E7EB;
}
</style>
{%endblock content%}
and here I want to have his informations.
user_profile.html
{% extends "base.html" %}
{%block content%}
{%load static%}
<div class="card float-left">
<img src="{% static 'images/img.jpg' %}" alt="John" style="width:100%">
{%if user.is_authenticated%}
<h3>{{user.first_name}} {{user.last_name}}</h3>
<p>{{user.email}}</p>
{%endif%}
<p class="title">CEO & Founder, Beehive</p>
<p>Istanbul Technical University</p
<p><button>Contact</button></p>
</div>
of course now it displays the information of the logged in user but I want to change it depending on which user he clicks
EDIT
now I am trying to get two models and the data from the first template to display on the second template with a cbv. Here is my new view.
class UserProfile(ListView):
template_name = 'user_profile.html'
model=PostModel
user=User.objects.get(username=username)
def get_context_data(self, **kwargs):
context = super(UserProfile, self).get_context_data(**kwargs)
context['posts'] = PostModel.objects.filter(author=user).order_by('created_on')
context['comments'] = CommentModel.objects.filter(author=user).order_by('created_on')
context['profile']=user
return context
but here I got the error:
name 'username' is not defined
You'll have to look the user up, e.g.:
#login_required
def user_profile(request, username):
if request.user.username != username:
user = User.objects.get(username=username)
else:
user = request.user
return render(request, "user_profile.html", {'profile': user})
You'll need to use {{ profile.username }} etc. in your template (Django has reserved {{ user.xxx }} for itself and will overwrite it.
You should probably add some more permissions to the view. As presented above, any logged in user can view any other logged in user's profile, i.e. change the if to:
if request.user.username != username and can_view(request.user, username):
....
(then implement the can_view(userobject, username) function).
#login_required
def user_profile(request, username):
if request.user.username != username:
user = User.objects.get(username=username)
else:
user = request.user
posts=PostModel.objects.filter(author=user)
comments=CommentModel.objects.filter(author=user)
return render(request, "user_profile.html", {'profile': user,'posts':posts,'comments':comments})
I solved my problem so and I am happy :)
I am using Django and I am trying when a button is clicked to get data from the database and fill a form with them through AJAX.
I get the error TypeError: Object of type 'EditProductForm' is not JSON serializablefrom the edit_product_view in my views.py
Below is the code I am working with:
-urls.py
from django.conf.urls import url
from . import views
app_name = "products"
urlpatterns = [url(r'^products', views.ProductsView.as_view(), name="products"),
url(r"^product/new", views.add_new_product_view, name="add_new_product"),
url(r"^product/(?P<id>[0-9]+)/edit/", views.edit_product_view, name="edit_product")]
-views.py
from django.views.generic import DetailView, ListView, TemplateView
from django.http import JsonResponse
from django.shortcuts import render, get_object_or_404
from . import models
from products.forms import AddNewProductForm, EditProductForm
def index(request):
return render(request, 'products/products.html')
class ProductsView(ListView):
context_object_name = "products"
model = models.Product
template_name = "products/products.html"
form = AddNewProductForm()
def get_context_data(self, **kwargs):
context = super(ProductsView, self).get_context_data(**kwargs)
context["products"] = models.Product.objects.all().order_by("title")
context["form"] = self.form
return context
def add_new_product_view(request):
if request.method == "POST":
form = AddNewProductForm(request.POST)
if form.is_valid():
form.save(commit=True)
return JsonResponse({'msg': 'Data saved'})
else:
print("ERROR FORM INVALID")
return JsonResponse({'msg': 'ERROR FORM INVALID'})
else:
form = AddNewProductForm()
return JsonResponse({'form': form})
def edit_product_view(request, id):
print(request.method)
instance = get_object_or_404(models.Product, id=id)
form = EditProductForm(instance=instance)
if request.method == "POST":
form = EditProductForm(request.POST, instance=instance)
if form.is_valid():
form.save(commit=True)
return JsonResponse({'form': form})
else:
print("ERROR FORM INVALID")
return JsonResponse({'form': form})
-products.html
{% extends "products/base.html" %}
{% load static %}
{% block title %}My Products{% endblock %}
{% block content %}
<div class="container" id="my-products-table-container">
<h2 class="text-left caption">Add, view and edit products</h2>
<hr>
<table class="table table-striped table-sm table-bordered" id="my-products-table">
<thead class="thead-inverse">
<tr class="head-row">
<th>Title</th>
<th>Description</th>
<th>Year</th>
<th>Manufacturer</th>
</thead>
<tbody>
{% for product in products %}
<tr class="table-row">
<td>{{ product.title }}</td>
<td>{{ product.description }}</td>
<td>{{ product.year_manufactured }}</td>
<td>{{ product.manufacturer }}</td>
<td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addNewProductModalForm">Add New product</button></td>
<td><button onclick="findMyForm({{ product.pk }})">Update product</button></td>
{% endfor %}
</tbody>
</table>
</div>
<!-- Modal Add New Product-->
<div class="modal fade" id="addNewProductModalForm" tabindex="-1" role="dialog" aria-labelledby="addNewProductModalFormLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form class="form" id="add_new_product_form">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addNewProductModalFormLabel">Add New Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% csrf_token %}
{{ form.as_p }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="addNewProduct()">Submit</button>
</div>
</div>
</form>
</div>
</div>
<!-- Modal Edit-->
<div class="modal fade" id="editProductModalForm" tabindex="-1" role="dialog" aria-labelledby="editProductModalFormLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<form class="form" id="edit_product_form" >
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editProductModalFormLabel">Edit Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{% csrf_token %}
<div id='showForm'></div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit!">
</div>
</div>
</form>
</div>
</div>
<!-- JS Scripts -->
<script src="{% static "products/js/addProduct.js" %}"></script>
<script>
function findMyForm(productKey) {
$('#editProductModalForm').modal('show');
$.ajax({
type: 'GET',
url: '/product/' + productKey + '/edit/',
success: function(res) {
$("#showForm").html(res);
}
})}
</script>
{% endblock %}
-addProduct.js
function addNewProduct(e) {
var addNewProductForm = $("#add_new_product_form");
$.ajax({
type: 'POST',
url: '/product/new/',
data: addNewProductForm.serialize(),
success: function(res){
alert(res['msg'])
}
})
}
What happens is that when I click <button onclick="findMyForm({{ product.pk }})">Update product</button> the function findMyForm({{ product.pk }}) runs.
Then a get request is called on '/product/' + productKey + '/edit/' through AJAX, based on the urls.py and views.py, edit_product_view is called to pass the form which is filled with the appropriate data.
At this point, it says that TypeError: Object of type 'EditProductForm' is not JSON serializable. I can't figure it out.
The object 'EditProductForm' is not JSON serializable, what you need is to return the form as HTML str, change your views.py:
from
return JsonResponse({'form': form})
to
return HttpResponse(form.as_p()) # return form as html str