django2: url based on pk not working - python

I want to have a form (webpage) for the model ImpCalendar so I can edit it's data.
The url should have the calendar_id (primary key), which i set in the urls.py
The model (ImpCalendar) has a ForeignKey to Establishments. I do not use that foreignkey in the view/form so i don't know if it is relevant.
If i do in views.py;
return render(request, 'importer/calendaredit.html', {'form': calendar})
i do see the data on a page, but not a (edit) form. Just the data, not the fill-in fields.
When i do
return render(request, 'importer/calendaredit.html', {'form': form})
which sounds logical to me, I get the error
django.urls.exceptions.NoReverseMatch: Reverse for 'calendaredit' with arguments '('',)' not found. 1 pattern(s) tried: ['importer\\/calendar\\/(?P<calendar_id>[0-9]+)\\/$']
It seems to me, the value returned for the calendar_id is now forms-data (html) which it can not do anything with. But i don't know what I am doing wrong. It has to do something with the html code and the values being transported to it, but i am last.
models.py
class Impcalendar(models.Model):
establishment = models.ForeignKey(Establishments, on_delete=SET_NULL, null=True)
url = models.CharField(max_length=255)
comment = models.CharField(max_length=255, null=True, blank=True)
status = models.IntegerField(null=True, blank=True)
def __str__(self):
return str(self.establishment)
forms.py
from django import forms
import datetime
from importer.models import Impcalendar, Establishments
class ImpcalendarForm(forms.ModelForm):
class Meta:
model = Impcalendar
fields = ['id', 'url']
urls.py
from django.urls import path
from importer import views
urlpatterns = [
path('', views.index, name='index'),
path('calendar/<int:calendar_id>/', views.calendaredit, name='calendaredit')
]
views.py
def calendaredit(request, calendar_id):
calendar = get_object_or_404(Impcalendar, pk=calendar_id)
print (calendar.url)
if request.method == 'POST':
form = ImpcalendarForm(request.POST, instance=calendar)
if form.is_valid():
calendar.save()
else:
form = ImpcalendarForm(request.POST or None, instance=calendar)
return render(request, 'importer/calendaredit.html', {'form': form})
calendaredit.html
{% extends 'importer/base.html' %}
{% block content %}
<h1>{{ form.id }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'calendaredit' form.id %}" method="post">
<div class="fieldWrapper">
{% csrf_token %}
{{ form.id }}
{{ form.url }}
</div>
<input type="submit" value="Save" />
</form>
{% endblock %}

You need to pass both things, calling them what they are, and reference the calendar not the form.
return render(request, 'importer/calendaredit.html', {'form': form, 'calendar': calendar})
...
<form action="{% url 'calendaredit' calendar.id %}" method="post">

Related

Django blog app won't display edit posts page

Currently working through the Python Crash Course Django section I've got everything but the edit posts page working. I added the edit post link under each post but this error now displays when you try to view the homepage:
Reverse for 'edit_post' with no arguments not found. 1 pattern(s) tried: ['edit_post/(?P<post_id>[0-9]+)/$']
Here is the code I've been using.
from django.db import models
# Create your models here.
class BlogPost(models.Model):
"""A topic the user is learning about"""
title = models.CharField(max_length=200)
body = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""A place for the user to create a blog post"""
return self.title
Views
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogForm
# Create your views here.
def index(request):
"""The home page for Blog"""
return render(request, 'blogs/index.html')
def blogposts(request):
"""Show all blogposts"""
blogposts = BlogPost.objects.order_by('date_added')
context = {'blogposts': blogposts}
return render(request, 'blogs/blogposts.html', context)
def new_post(request):
"""Add a new post"""
if request.method != 'POST':
# No data submitted, create a blank form
form = BlogForm()
else:
# POST data submitted; process data
form = BlogForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:blogposts')
# Display a blank or invalid form
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, post_id):
current_entry = BlogPost.objects.get(id=post_id)
if request.method != 'POST':
# Initial request; pre-fill form with current entry
form = BlogForm(instance=current_entry)
else:
form = BlogForm(instance=current_entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:index')
context = {'post':post, 'form':form}
return render(request, 'blogs/edit_post.html', context)
URLs
"""Defines URL patterns for blogs"""
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page
path('', views.index, name='index'),
# Page that shows all topics
path('blogposts/', views.blogposts, name='blogposts'),
# Page that displays a single post
path('new_post/', views.new_post, name='new_post'),
# Page for editing a post
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
blogposts.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Blog Posts</p>
<ul>
{% for blogpost in blogposts %}
<h1>{{ blogpost }}</h1>
<p>{{ blogpost.body }}</p>
Edit post
{% empty %}
<li>No blogs have been posted yet</li>
{% endfor %}
</ul>
Create a new post
{% endblock content %}
edit_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>Edit post:</p>
<form action="{% url 'blogs:edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save Changes</button>
</form>
{$ endblock content %}
You need to pass the id of the blog post you want to edit.
So in your blogposts.html try:
"{% url 'blogs:edit_post' blogpost.pk %}"

NoReverseMatch Django 2 Python

NoReverseMatch
Reverse for 'Edit_Product' with no arguments not found. 1 pattern(s) tried: ['shop/product/Edit_Product/(?P[0-9]+)$']
I could not understand the reason behind this error I tried looking for answers for around the web but nothing worked for me so far, I am new to django and trying to develop my skills if anyone can help please
Models.py
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products',
on_delete=models.CASCADE)
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d',
blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('name',)
index_together = (('id', 'slug'),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:product_detail', args=[self.id, self.slug])
forms.py
class EditProduct(forms.ModelForm):
class Meta:
model = Product
fields = ["category", "name", "image", "description",
"price", "available"]
views.py
#staff_member_required
def Edit_Product(request, id=None):
product = get_object_or_404(Product, id=id)
if request.method == "POST":
form = EditProduct(request.POST, instance=product)
if form.is_valid():
form = form.save(commit=False)
form.save()
return render(request, 'shop/product/Edit_Product.html', {'product': product, 'form':form})
else:
form = EditProduct(instance=product)
return render(request,'shop/product/Edit_Product.html', {'form': form})
urls.py
urlpatterns = [
path('', views.product_list, name='product_list'),
path('<slug:category_slug>/', views.product_list, name='product_list_by_category'),
path('<int:id>/<slug:slug>/', views.product_detail, name='product_detail'),
path('shop/Create_Product/', views.Create_Product, name='Create_Product'),
path('shop/product/Edit_Product/<int:id>', views.Edit_Product, name='Edit_Product'),
]
the templates look like this
{% extends "shop/base.html" %}
{% load static %}
<title> Edit </title>
{% block content %}
<div>
<form action="{% url 'shop:Edit_Product' id=Product.id %}" method="POST" enctype="multipart/form-data">
{{ form.as_p }}
<p><input type="submit" value="Update"></p>
{% csrf_token %}
</form>
</div>
{% endblock %}
I would be really grateful for any help I have been having for days now and when modifying it I receive either this error or 404 error.
the error is showing me the detailproduct view in the browser I tried arranging them making edit before it and add it to the render line but alos no luck there
This is how it looks like the view.py product detail just after the edit
def product_detail(request, id, slug):
product = get_object_or_404(Product,
id=id,
slug=slug,
available=True)
cart_product_form = CartAddProductForm()
return render(request,
'shop/product/detail.html',
{'product': product,
'cart_product_form': cart_product_form})
the Image link is here for the Error
enter image description here
Detail.html
{% block content %}
<div class="product-detail">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}">
<h1>{{ product.name }}</h1>
<h2>{{ product.category }}</h2>
<p class="price">${{ product.price }}</p>
<form action="{% url "cart:cart_add" product.id %}" method="post">
{{ cart_product_form }}
{% csrf_token %}
{% if request.user.is_staff %}
Edit Product
{% endif %}
<input type="submit" value="Add to cart">
</form>
{{ product.description|linebreaks }}
You should try to understand the error:
NoReverseMatch Reverse for 'Edit_Product' with no arguments not found.
This error is saying that you asked Django to reverse a url pattern with the name Edit_Product, that it expects an argument but no argument was given.
Indeed, this is your path:
path('shop/product/Edit_Product/<int:id>', views.Edit_Product, name='Edit_Product')
so in order to reverse it, you need to pass it the argument id:
# in a view
from django.urls import reverse
reverse('Edit_Product', kwargs={'id': <some_id>})
# in a template
{% url 'Edit_Product' id=<some_id> %}
You can now just search in your entire project for reverse('Edit_Product' and {% url 'Edit_Product' or narrow it down like this:
First, this is not an error in your Edit_Product view (at least not necessarily), it can happen in any view that reverses the url pattern. You need to look at the rest of the error message which tells you which url was requested or which view was used.
You already saw that this was happening in the product_detail() view, in the render() method actually.
So the error was triggered when rendering the template, in this case the detail.html template. Here you should check for {% url 'Edit_Product' ... %}.
There you have it, {% url 'Edit_Product' %} with no argument. Fix it by adding the product.id.

Editing posts in a Django blog

Note: there's a similar question to mine, there're a few differences in our code, and I tried the solutions to his question, didn't work for me.
I'm working on a blog using Django, I'm trying to add an edit_post feature but when I go to localhost:8000 it shows NoReverseMatch, the problem is related to the post's id, I'm trying to create a home page that shows the post's title and it's content.
here'e my code:
models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
title = models.CharField(max_length=20)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
urls.py
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page
path('', views.index, name='index'),
# page for adding a new post
path('new_post/', views.new_post, name='new_post'),
# page for editing a post
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
index.html
{% block content %}
<p>My personal Blog</p>
Add a new post
<ul>
{% for p in posts %}
# the problem is probably here
<li>{{ p.title }}</li>
<li>{{ p.text }}</li>
<p>
Edit post
</p>
{% endfor %}
</ul>
{% endblock content %}
edit_post.html
{% block content %}
<p>Edit post:</p>
<form action="{% url 'blogs:edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submet">Save changes</button>
</form>
{% endblock content %}
new_post.html
{% block content %}
<P>Add a new post:</P>
<form action="{% url 'blogs:new_post' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submet">Add post</button>
</form>
{% endblock content %}
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
# Create your views here.
def index(request):
posts = BlogPost.objects.order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/index.html', context)
def new_post(request):
"""Add a new post."""
if request.method != 'POST':
form = BlogPostForm()
else:
form = BlogPostForm(data=request.POST)
if form.is_valid():
new_p = form.save()
return redirect('blogs:index')
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
if request.method != 'POST':
form = BlogPostForm(instance=post)
else:
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:index', post_id=post.id)
context = {'post': post, 'index': index, 'form': form}
return render(request, 'blogs/edit_post.html', context)
forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols':80})}
The problem is with the arguments of the url you are creating on index.html, you are looping posts as p in html so try to change:
Edit post
With
Edit post

How can I get data from a form model into a database in Django

I am trying to get data from a model form and then put it into a database. I have figured out how to make the form, but when clicking the submit button it doesn't seem to be put anywhere in my database. Am I doing anything wrong or am I not looking in the correct place in the database.
forms.py
from django import forms
from sxsw.models import Account
class AccountForm(forms.ModelForm):
class Meta:
model = Account
fields = ['firstName', 'lastName', 'email']
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from .forms import AccountForm
from .models import Account
def sxsw(request):
if request.method == 'POST':
form = AccountForm(request.POST)
if form.is_valid():
form.save()
else:
print form.errors
else:
form = AccountForm()
return render(request, 'sxsw/sxsw.html', {'form': form})
def formSubmitted(request):
return render(request, 'sxsw/formSubmitted.html',{})
models.py
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Account(models.Model):
firstName = models.CharField(max_length = 50)
lastName = models.CharField(max_length = 50)
email = models.EmailField()
def __unicode__(self):
return self.firstName
class Module(models.Model):
author = models.ForeignKey(Account, on_delete = models.CASCADE)
nameOfModule = models.CharField(max_length = 150) #arbitrary number
moduleFile = models.FileField(upload_to = 'uploads/')#Not exactly sure about the upload_to thing
public = models.BooleanField()
def __unicode__(self):
return self.nameOfModule
sxsw.html
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron text-center">
<h3>SXSW Form</h3>
</div>
</div>
<div align="center">
<h1>New Form</h1>
<form role='form' action="/sxsw/formSubmitted/" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
</div>
</div>
{% endblock %}
formSubmitted.html
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron text-center">
<h3>Form Successfully submitted</h3>
</div>
</div>
<div align="center">
Submit Another Response
</div>
</div>
{% endblock %}
Your form is posting to what I presume is the wrong url
<form role='form' action="/sxsw/formSubmitted/" method="post">
should use the url for the sxsw view
<form role='form' action="/sxsw/" method="post">
Once submitted, you'll likely want to redirect to the submitted view
return redirect('/sxsw/formSubmitted/') # Preferably use the url pattern name here
It looks like your form's action is set to /sxsw/formSubmitted/ that always simply return the submitted page, instead of the url that will call the sxsw view where the form's save method is called.

Recover the data already recorded in my Django admin space in my form

I want to know how to retrieve answers already made in my text fields because there is no ways to retrieve the answers already registered!
This is my models :
class Patient(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name + ' [' + str(self.id) + ']'
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question_text
class Reply(models.Model):
question = models.ForeignKey(Question)
patient = models.ForeignKey(Patient)
reply_text = models.CharField(max_length=200)
def __unicode__(self):
return self.reply_text
This is my template (formDynamic.html) :
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'Forum/style.css' %}" />
<div>
<h1>Patient details : {{ patient }}</h1>
</div>
form-included-into-question-template -->
<form action="success" method="post">
{% csrf_token %}
<fieldset>
{% block content %}
{% for question in questions %}
<h2><abcd>{{ question }}</abcd> <h6>{{ question.pub_date }}</h6></h2>
{% for reply in form %}
{{ form }}
{% endfor %}
{% endfor %}
{% endblock %}
</fieldset>
<input type="submit" value="Submit"/>
</form>
<a href="{% url 'list_patient' %}"/> <input type="button" value="Look Back"/>
This is my urls :
from django.conf.urls import url
from .import views
urlpatterns = [
url(r'^$', views.list, name ='list_patient'),
url(r'^(?P<patient_id>[0-9]+)/patient/$', views.save_reply, name ='detail_patient'),
#url(r'^(?P<patient_id>[0-9]+)/patient/success$', 'success', name ='success'),
]
This is my forms.py :
from django.forms import ModelForm
from django import forms
from .models import Reply
class ReplyForm(ModelForm):
class Meta:
model = Reply
fields = ['reply_text']
This is my views.py :
def save_reply(request, patient_id):
patient = get_object_or_404(Patient, pk=patient_id)
questions = Question.objects.all()
if request.method == 'POST':
form = Replyform(request.POST)
if form.is_valid():
new_obj = form.save(commit=False)
new_obj.creator = request.user
u = Question.objects.get(pk=id)
new_obj.reply_to = u
new_obj.save()
return HttpResponseRedirect('/success')
else:
form = ReplyForm()
return render_to_response('PQR/formDynamic.html', {'form': form, 'questions': questions, 'patient': patient,}, context_instance=RequestContext(request))
def success(request):
return HttpResponse ('<p>Success</p>')
I can not retrieve the answers already registered and run my post method to save my answers and return me the URL /success.
My post method does not work as well as my redirect to my url / success. Thanks you for your help !
I don't understand your question, but the reason you can't submit your form is that it is posting to a non-existent destination: the action attribute in the form HTML tag needs to be an actual URL. If you want to use a view name then do so via the {% url %} tag:
<form action="{% url "success" patient_id=patient.id %}" method="post">

Categories

Resources