how to set variable through views in django - python

how to set any variable in views so that its value i will get in template
home.html
<html>
<head>
<title>To-Do lists</title>
</head>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input id="id_new_item" name="item_text" placeholder="Enter a To-Do item"/>
{% csrf_token %}
</form>
<table id="id_list_table">
<tr><td>1 : {{new_item_text}}</td></tr>
</table>
</body>
views.py
from django.shortcuts import render
from django.http import HttpResponse
from lists.models import Item
def home_page(request):
if request.method == 'POST':
new_item_text = request.POST['item_text'] #
print new_item_text;
Item.objects.create(text=new_item_text) #
else:
new_item_text = '' #
item = Item()
item.text = request.POST.get('item_text', 'A new list item')
item.save()
return render(request, 'home.html', {
'new_item_text': new_item_text
})
MODELS.PY
from django.db import models
class Item(models.Model):
text = models.TextField(default='')
This is the test that is failing
test.py
def test_home_page_returns_correct_html(self):
request = HttpRequest() #
response = home_page(request) #
self.assertIn('A new list item', response.content.decode())
expected_html = render_to_string('home.html',
{'new_item_text': 'A new list item'}
)
self.assertEqual(response.content.decode(), expected_html)
the error is
AssertionError: 'A new list item' not found in u'<html>\n\t<head>\n\t\t<title>To-Do lists</title>\n\t</head>\n\t<body>\n\t\t<h1>Your To-Do list</h1>\n\t\t<form method="POST">\n\t\t<input id="id_new_item" name="item_text" placeholder="Enter a To-Do item"/>\n\t\t\n\t\t</form>\n\t\t<table id="id_list_table">\n\t\t\t<tr><td>1 : </td></tr>\n\t\t</table>\n\t</body>\n</html>\n'
please tell me the solutions or any material(any link) for question that i asked

Templates get rendered with some context data, this is where you can pass through variables. In the case of Class Based Views as Imran suggested you can return your context from the
get_context_data method.
In function views you can pass context through to the render shortcut
return render(request, 'my-template.html', {"variable1": True, "variable3": foo})

you should use class based view
class HomeView(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context['user']= self.request.user.username
return context
in view you can simply access user as
{{user}}

Related

How to modify a form when returning it?

I am looking to modify a form from the user and return that different form in django, however I have tried many different ways, all in views.py, including:
Directly modifying it by doing str(form) += "modification"
returning a new form by newform = str(form) + "modification"
creating a different Post in models, but then I realized that wouldn't work because I only want one post
All the above have generated errors such as SyntaxError: can't assign to function call, TypeError: join() argument must be str or bytes, not 'HttpResponseRedirect', AttributeError: 'str' object has no attribute 'save', and another authority error that said I can't modify a form or something like that.
Here is a snippet from views.py:
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['content']
title = ['title'] #
template_name = 'blog/post_new.html'
success_url = '/'
def form_valid(self, form):
#debugging
tempvar = (str(form).split('required id="id_content">'))[1].split('</textarea></td>')[0] #url
r = requests.get(tempvar)
tree = fromstring(r.content)
title = tree.findtext('.//title')
print(title)
form.instance.author = self.request.user
if "http://" in str(form).lower() or "https://" in str(form).lower():
if tempvar.endswith(' '):
return super().form_valid(form)
elif " http" in tempvar:
return super().form_valid(form)
elif ' ' not in tempvar:
return super().form_valid(form)
else:
return None
models.py:
class Post(models.Model):
content = models.TextField(max_length=1000)
title = models.TextField(max_length=500, default='SOME STRING') #
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes= models.IntegerField(default=0)
dislikes= models.IntegerField(default=0)
def __str__(self):
return (self.content[:5], self.title[:5]) #
#property
def number_of_comments(self):
return Comment.objects.filter(post_connected=self).count()
And in home.html, where the post (along with the title and content) is supposed to be shown:
<a
style="color: rgba(255, 255, 255, 0.5) !important;"
href="{% url 'post-detail' post.id %}">
<p class="mb-4">
{{ post.content }}
{{ post.title }} #
</p>
</a>
The original template I'm modifying can be found here.
Thank you so much for your help, I will be very glad to take any advice!!
Ps: I'm using Python 3.7.4
Create a forms.py file inside the app you are talking about, it should look like this:
from django import forms
from . import models
class YourFormName(forms.ModelForm):
class Meta:
model = models.your_model_name
fields = ['field1', 'field2' ,...] # Here you write the fields of your model, this fields will appear on the form where user post data
Then you call that form into your views.py so Django can render it into your template, like this:
def your_view(request, *args, **kwargs):
if request.method == 'POST':
form = forms.YourFormName(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.user= request.user
instance.save()
return redirect('template.html') # To redirect if the form is valid
else:
form = forms.YourFormName()
return render(request, "template.html", {'form': form}) # The template if the form is not valid
And the last thing to do is create the template.html:
{% extends 'base.html' %}
{% block content %}
<form action="{% url 'the_url_that_renders_this_template' %}" method='POST' enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
{% endblock content %}
If you want to take the data from DB submitted in that form, you do so with a new function in views.py:
def show_items(request, *args, **kwargs):
data = YourModelName.objects.all()
context = {
"data": data
}
return render(request, "show_items.html", context)
Then in show_items.html:
{% extends 'base.html' %}
{% block content %}
{% for item in data %}
{{item.field1}}
{{item.field2}}
...
{{The items you want to show in that template}}
{% enfor %}
{% endblock content %}
That's what you wanted to do? If not, add a further explanation on what actually you want to do

Method Not Allowed (POST) in Django 3.0.7

I'm new to Django. I 'm trying to practice create Raw Update Class Based View but it get in to error Method Not Allowed (POST). Can any one help me please.
I already follow the instruction step by step but the result is the same. I also try a lot of method to fix but still can't. I really want to know what is the problem. I very appreciate for someone help me fix this.
view.py
from django.shortcuts import render, get_object_or_404
from django.views import View
from .models import Client
from .forms import ClientFrom
class ClientUpdateView(View):
template_name = "clients/client-update.html"
def get_object(self):
id = self.kwargs.get('id')
obj = None
if id is not None:
obj = get_object_or_404(Client, id=id)
return obj
def get(self, request, id=None, *args, **kwargs):
#GET Method
context = {}
obj = self.get_object()
if obj is not None:
form = ClientFrom(instance=obj)
context['object'] = obj
context['form'] = form
return render(request, self.template_name, context)
def post(self, request, id=None, *args, **kwargs):
#POST Method
context = {}
obj = self.get_object()
if obj is not None:
form = ClientFrom(request.POST, instance=obj)
if form.is_valid():
form.save()
context['object'] = obj
context['form'] = form
return render(request, self.template_name, context)
forms.py
from django import forms
from .models import Client
class ClientFrom(forms.ModelForm):
class Meta:
model = Client
fields = [
'Name',
'Address',
'Contact',
]
form in client-update.html
{% extends 'clienthead.html' %}
{% block content %}
<h1>Update: {{object.id}} - {{ object.Name }}</h1>
<form action='.' method='POST'> {% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Save' />
</form>
{% endblock %}
urls.py
from django.urls import path
from .views import (
ClientUpdateView,
)
app_name = 'client'
urlpatterns = [
path('<int:id>/adjust', ClientUpdateView.as_view(), name='client-adjust'),
]

Update a single object from a database - Django/Python

So I am trying to allow users to edit menu item prices that are in the database currently. The fields will auto-populate data into the page and users will be able to edit that data to change the price. Here is what I have. I have tried and asked many questions, but I am still lost. I have googled a lot and it helped me understand forms a bit, but I'm not able to fix it. Please let me know if you need more info.
Views.py:
def edit_menu(request):
queryset = Product.objects.all()
context = { "object_list": queryset }
if request.method == 'POST':
post=ProductModelForm(request.POST)
if request.POST.get('price') and request.POST.get('name'):
if 'name' == Product.name:
post.name= request.POST.get('name')
post.price= request.POST.get('price')
post.save()
return redirect('Edit Menu Item')
else:
return redirect('Edit Menu Item')
else:
return render(request, 'mis446/edit-menu-item.html', context)
else:
return render(request, 'mis446/edit-menu-item.html', context)
forms.py:
class ProductModelForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name','price'] # specify which field you need to be in the form
HTML:
<title>ACRMS - Edit Menu Price</title>
<div class = "container">
<form action = "" method = 'POST'>
{% csrf_token %}
{% for instance in object_list %}
<input name = "name" value = "{{ instance.name }}"></input>
<input type="number" name="price" value = "{{ instance.price }}"/><br>
{% endfor %}
</select>
<button type ="submit">Submit Changes</button>
</form>
</div>
Urls.py:
url('edit-menu/edit/',views.edit_menu, name='Edit Menu Item'),
models.py:
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.IntegerField()
slug = models.SlugField()
def __str__(self):
return self.name
For your current implementation, you do not need a form. Instead, update the view like this:
# view
def edit_single_menu(request, pk):
if request.method == 'POST':
post=Product.objects.get(pk=pk)
if request.POST.get('price') and request.POST.get('name'):
post.name= request.POST.get('name')
post.price= request.POST.get('price')
post.save()
return redirect('Edit Menu Item')
else:
return redirect('Edit Menu Item')
return render(request, 'mis446/edit-menu-item.html', context)
# url
url('edit-menu/edit/<pk:id>/',views.edit_single_menu, name='edit_single_menu'),
# template (mis446/edit-menu-item.html)
<title>ACRMS - Edit Menu Price</title>
<div class = "container">
{% for instance in object_list %}
<form action = "{% url 'edit_single_menu' instance.pk %}" method = 'POST'>
{% csrf_token %}
<input name = "name" value = "{{ instance.name }}"></input>
<input type="number" name="price" value = "{{ instance.price }}"/><br>
<button type ="submit">Submit Changes</button>
</form>
{% endfor %}
</div>
Here I am sending individual edit to a new separated view named edit_single_menu and store the changes there.
Update
New url is not meant to replace the old one. It is only to assist you to update individual product. So, you need to keep both of the urls. Also, here is an answer based on #brunodesthuilliers's suggestion:
# view
def edit_single_menu(request, pk):
if request.method == 'POST':
post=Product.objects.get(pk=pk)
form = ProductForm(request.POST, instance=post)
if form.is_valid():
form.save()
return redirect('Edit Menu Item')
Also, do some changes on edit_menu view:
def edit_menu(request):
queryset = Product.objects.all()
context = { "object_list": queryset }
return render(request, 'mis446/edit-menu-item.html', context)
And urls should look like this:
from django.urls import include, path
# rest of the code
path('edit-menu/edit/<int:pk>/',views.edit_single_menu, name='edit_single_menu'),
path('edit-menu/edit/',views.edit_menu, name='Edit Menu Item'),

input fields not displaying on templates

i am new to django when i try to run this project i wasn't getting any input fields in my template current page was only showing the given labels
i don't know where i've gone wrong
can any of you guys help??
these are my models.py file
from django.db import models
# Create your models here.
class Student(models.Model):
sid = models.CharField(max_length=100)
sname = models.CharField(max_length=100)
sclass = models.CharField(max_length=100)
semail = models.EmailField(max_length=100)
srollnumber = models.CharField(max_length=100)
scontact = models.CharField(max_length=100)
saddress = models.CharField(max_length=100)
class Meta:
db_table = "student"
the are my forms.py file
from django import forms
from student.models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = "__all__"
these are my views.py file
from django.shortcuts import render
from student.models import Student
from student.forms import StudentForm
def student_home(request):
return render(request, 'employee/dash.html')
def add_student(request):
if request.method == "POST":
form = StudentForm(request.POST)
if form.is_valid():
try:
form.save()
return render(request, 'employee/dash.html')
except:
pass
else:
form = StudentForm()
return render(request, 'student/addstudent.html')
template
<!DOCTYPE html>
<html lang="en">
<head>
<title>addstudent</title>
</head>
<body>
<a href="/home" >home</a>
<form method="POST" action="/add_student">
{% csrf_token %}
<label>Student ID:</label>
{{ form.sid }}
<label>Name :</label>
{{ form.sname }}
<label>Class :</label>
{{ form.sclass }}
<label>Email ID:</label>
{{ form.semail }}
<label>Roll Number :</label>
{{ form.srollnumber }}
<label>Contact :</label>
{{ form.scontact }}
<label>Address :</label>
{{ form.saddress }}
<button type="submit">Submit</button>
</form>
</body>
</html>
You forget to give the context to the render function:
return render(request, 'student/addstudent.html',context={'form':form})
should work
You have not included any context in your render functions. Your view should be:
def add_student(request):
if request.method == "POST":
form = StudentForm(request.POST)
if form.is_valid():
try:
form.save()
return render(request, 'employee/dash.html', context={'form': form})
except:
pass
else:
form = StudentForm()
return render(request, 'student/addstudent.html', context={'form': form})

Search in django doesn't work

I am trying to have search option i my page. I have tried the method given in the standard django document in this link 'https://docs.djangoproject.com/en/1.11/intro/tutorial01/', but my search function isn't working. only the url changes from http://localhost:8000/contact this to http://localhost:8000/contact/your-contact/?q=harini but datas are not filtered and displayed. I am using django 1.11. Could anyone help me with it? Thanks in advance
models.py
from __future__ import unicode_literals
from django.db import models
class ContactModel(models.Model):
name = models.CharField(max_length=200)
dob = models.DateField()
phone_number = models.IntegerField()
gender = models.BooleanField()
address = models.CharField(max_length=200)
views.py
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.views import generic
from django.template.response import TemplateResponse
from django.views.generic import CreateView
from django.urls import reverse_lazy
from .models import ContactModel
from .forms import ContactForm
class ContactView(CreateView):
model_class = ContactModel
form_class = ContactForm
success_url = reverse_lazy('contact-thanks')
initial = {'name': 'value'}
template_name = 'contact/contact.html'
def get(self, request, *args, **kwargs):
model = self.model_class()
return render(request, self.template_name, {'model': ContactForm})
def post(self, request, *args, **kwargs):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('thanks/')
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
class ContactlistView(CreateView):
model = ContactModel
template_name = 'contact/contactlist.html'
def search(request):
query = request.GET['q']
t = loader.get_template('template/contact/contactlist.html')
c = Context({ 'query': query,})
if query:
results = Contact.objects.filter(Q(name__icontains=query) |
Q(dob__icontains=query) |
Q(address__icontains=query) |
Q(gender__icontains=query) |
Q(phone_number__icontains=query))
return render(request, 'contactlist.html', {'form': form})
else:
return render(request, 'contactlist.html', {'form': form})
urls.py
from django.conf.urls import url
from . import views
app_name = 'contact'
urlpatterns = [
url(r'^$', views.ContactView.as_view(), name='contact'),
url(r'^your-contact/$', views.ContactView.as_view(), name='contact'),
url(r'^your-contact/thanks/$', views.ContactView.as_view(), name='contact'),
url(r'^contact-list/$', views.ContactlistView.as_view(), name='contactlist'),
url(r'^contact-list/your-contact/$', views.ContactlistView.as_view(), name='contactlist'),
]
templates/contact/contactlist.html
<form method="get" action="contact-list/">
<input type="text" id="searchBox" class="input-medium search-query" name="q" placeholder="Search" value= "{{ request.GET.q }}">
{% if contact %}
{% for each_contact in contacts %}
<h3>Name: {{ contact.name }}</h3>
<p>Dob: {{ contact.dob }}</p>
<p>Gender: {{ contact.gender }}</p>
<p>Address: {{ contact.address }}</p>
<p>Phone Number: {{ contact.phone_number}}</p>
{% endfor %}
{% endif %}
<input type="submit" class="btn" value="Search" >
</form>
Your form action is pointed to your-contact/
<form method="get" action="your-contact/">
So this URL calls the view ContactView(), whereas the search query process is in the ContactlistView() view
class ContactlistView(CreateView):
''' '''
def search(request):
query = request.GET['q']
A solution is:
a little edit in your URLs patterns:
url(r'^contact-list/$', views.ContactlistView.as_view(), name='contactlist'),
And change the form action url and point it to this view ContactlistView(): with contact-list/
<form method="get" action="contact-list/">
Don't forget to replace if q: with if query:
I think the view as you have it right now is doing nothing, you should modify it in:
class ContactlistView(CreateView):
model = ContactModel
template_name = 'contact/contactlist.html'
def get(self, request):
query = request.GET['q']
t = loader.get_template('template/contact/contactlist.html')
c = Context({ 'query': query,})
if query:
results = Contact.objects.filter(Q(name__icontains=query) |
Q(dob__icontains=query) |
Q(address__icontains=query) |
Q(gender__icontains=query) |
Q(phone_number__icontains=query))
return render(request, 'contactlist.html', {'form': form})
else:
return render(request, 'contactlist.html', {'form': form})
Also please note a couple of things:
you're inheriting froma CreateView but you are not creating anything and you are not getting any advantage from that view, you should use a GenericView instead
you're defining the template as class attribute but then you are rendering you are doing everything manually because you are not getting (again) advantage of the CBV

Categories

Resources