I'm learning Django framework and I have in the extend templates part, I'm trying to add a new template when I click in the title of the post in my blog to redirect to an page with the post details (date/author/etc),so I create a new view in views.py and a new url to in urls.py,But when I adc the path of the url in the 'href' desirable of the .html file ,as you will see, I receive the follow error when I reload the page:
NoReverseMatch at /
Reverse for 'blog.views.post_detail' with arguments '()' and keyword
arguments '{'pk': 2}' not found. 0 pattern(s) tried: []
And
Error during template rendering
In template
/home/douglas/Documentos/Django/my-first-blog/blog/templates/blog/post_list.html,
error at line 9
So, when I erase the href to back the default value all works well...I am almost sure that something is wrong in the href line but I will post all template related files for you to check, if you need to check anything else let me know:
firs the html file: post_list.html
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<div class="date">
{{ post.published_date }}
</div>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
{% endblock content %}
urls.py:
from django.conf.urls import url
from . import views
from .models import Post
urlpatterns = [
url(r'^$', views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
]
views.py
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from .models import Post
from django.utils import timezone
def post_list(request):
#posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
Well guys, I think is that, I hope I have not forgotten any details about my question...
Thank you in advance,any help is welcome!!
You need to define a name for your url. It's better.
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
]
Like this, in your template, you can use this name on url tag
<h1>{{ post.title }}</h1>
First info (with name define for url)
The first argument is a url() name. It can be a quoted literal or any
other context variable.
Second info (In your case, url without name)
If you’d like to retrieve a namespaced URL, specify the fully
qualified name:
{% url 'myapp:view-name' %}
More information here
Related
I am building a "game" website where clues are given and individuals will make guesses.
I have added home.html, new_game.html, game_detail.html, base.html, and now edit_game.html. All is working correctly to create a new, list (in home.html), and display details. Now I am adding the function to edit the game in edit_game.html.
When I add the html link `Edit Game in game_detail.html, I get the error (below) when I click on any of the games in the list, which should display the game_detail page. In other words, it will not display the game_detail.html. Here is the error:
NoReverseMatch at /post/2/
Reverse for 'edit_game' with arguments '('',)' not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9]+)/edit/$']
It is clearly passing the ID of the post. But it is not picking up the "/edit/". Here is the detail page code:
<!-- templates/game_detail.html -->
{% extends 'base.html' %}
{% block content %}
<div class="post-entry">
<h2>{{object.title}}</h2>
<p>{{ object.body }}</p>
</div>
Edit Game
{% endblock content %}
Here is the urls code:
from django.urls import path
from .views import (
GameListView,
GameDetailView,
GameCreateView,
GameUpdateView,
)
urlpatterns = [
path('post/<int:pk>/edit/', GameUpdateView.as_view(), name='edit_game'),
path('post/<int:pk>/', GameDetailView.as_view(), name='game_detail'),
path('post/new/', GameCreateView.as_view(), name='new_game'),
path('', GameListView.as_view(), name='home'),
]
The Views code:
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView, UpdateView
from .models import Game
class GameListView(ListView):
model = Game
template_name = 'home.html'
class GameDetailView(DetailView):
model = Game
template_name = 'game_detail.html'
class GameCreateView(CreateView):
model = Game
template_name = 'new_game.html'
fields = ['title', 'author', 'body']
class GameUpdateView(UpdateView):
model = Game
template_name = 'edit_game.html'
fields = ['title', 'body']
The object is passed as object and game to the template, you can thus construct the link with:
{% url 'edit_game' game.pk %}
or:
{% url 'edit_game' object.pk %}
First of all; I'm fairly new to Django.
Right now, I'm trying to create a very simple webpage with links (just to learn). The idea right now is, that a user (which is logged in) can add links to the database/model, and only see the links of which he has added.
I'm strugling to figure out what the best practice is for that - is it to store the user.username in the model, and then make a .filter(username=user) each time or..? I would assume Django has some (faster way) of handling this.
I have the following
models.py
from django.db import models
from django.contrib.auth.models import User
class links(models.Model):
link = models.URLField()
#user = <something_here>
views.py
def add_link(request):
if request.method == "POST":
form = add_link_form(request.POST)
if form.is_valid():
messages.success(request, "Link is added!")
form.save()
return redirect("my_links")
else:
form = add_link_form()
context = {
"links":links.objects.all(),
"form":form
}
return render(request, "django_project/my_links.html",context=context)
my_links.html
{% extends "django_project/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
{{form|crispy}}
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Add link</button>
</div>
</form>
{% for l in links%}
{{l.link}}
{% endfor%}
{% endblock content %}
You can define Link as:
class Link(models.Model):
link = models.URLField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="links")
where, when adding you could do:
logged_in_user.links.create(...)
or if adding an already existing link:
logged_in_user.links.add(link)
or if you know that links will forever remain as as strings without any other data related to it, and you use postgresql as your DB, you could add this field to the user model:
from django.contrib.postgres.fields import ArrayField
from django.db import models
class UserModel(models.Model):
...
links = ArrayField(models.URLField(), default=list)
and when adding, treat it exactly as you would do with an array:
logged_in_user.links.append("google.com")
logged_in_user.save()
Both of these approaches, in essence, provide you a filtered list when calling logged_in_user.links, but in the first case it is a queryset of Link objects, whereas the second is an array of strings.
models.py
class Blog(models.Model):
title = models.CharField(max_length=100, unique=True)
slug = models.CharField(max_length=100, unique=True)
post_pic = models.ImageField(upload_to ='media/post_pics/', default =None )
body = models.TextField()
posted = models.DateTimeField(db_index=True, auto_now_add=True)
#author = must be logged in, populate from login details
forms.py
class postForm(forms.Form):
title = forms.CharField(max_length=100)
slug = forms.CharField(max_length=100)
post_pic = forms.ImageField()
body = forms.CharField(widget=SummernoteWidget())
views.py
def write_detail(request):
template_name = 'blog/write.html'
if request.method == 'POST':
post_form = postForm(request.POST)
if post_form.is_valid():
new_post = Blog(title=title,slug=slug,post_pic=post_pic,body=body)
new_post.save()
return HttpResponseRedirect(blog.get_absolute_url())
else:
post_form = postForm()
return render(request, template_name, {'post_form': post_form})
write.html
{% extends 'blog/base.html' %}
{% load static %}
{% block back-img %}'{% static 'blog/assets/img/intro.jpg' %}'{% endblock back-img %}
{% block titdes %}Write{% endblock titdes %}
{% block title %}Write{% endblock title %}
{% block pagedes %}A django powered community blog{% endblock pagedes %}
{% block body%}
<form method = "POST">
{{ post_form.as_p }}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Publish</button>
</form>
{% endblock %}
I have set up this form so that authors can write articles to the blog without accessing the admin panel and I believe it should work but it isn't saving to the database.
I have tried to work on the views over and over but don't know what else to do. Please don't delete my question just ask any question that can help you help me.
in your forms.py
try
from .models import Blog
class postForm(forms.Form):
title = forms.CharField(max_length=100)
slug = forms.CharField(max_length=100)
post_pic = forms.ImageField()
body = forms.CharField(widget=SummernoteWidget())
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic', 'body')
PS. Iam new to Django, i hope this help you.
It looks like you just need to save the form, but you're creating a new Blog object with values that we can't see defined anywhere.
new_post = Blog(title=title,slug=slug,post_pic=post_pic,body=body)
title, slug, etc don't get defined.
What you should do, is change it to a ModelForm so that django does all the hard work;
class postForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic', 'body')
widgets = {
'body': SummernoteWidget(),
}
Then in your view you just need to do;
def write_detail(request):
template_name = 'blog/write.html'
if request.method == 'POST':
post_form = postForm(request.POST)
if post_form.is_valid():
post_form.save()
return HttpResponseRedirect(blog.get_absolute_url())
else:
# GET request
post_form = postForm()
return render(request, template_name, {'post_form': post_form})
The summernote docs for forms (and modelforms) is here
Don't forget, that when using a widget like this that comes with media, you need to add the form's media to the template.
You can access it in the HTML using either {{ form.media }} to get all CSS and JS, or individually as {{ form.media.js }} and {{ form.media.css }}
You can see how they do it in the summernote app playground
class postForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'slug', 'post_pic','body')
widgets = {
'body':SummernoteWidget(),
}
Sorry guys you can actually use django summer note with a model form. I used it before but the editor was not appearing so I changed it to the one I previously posted but after reading another answer on stack overflow. I found out that I didn't add this code below to my HTML files or just inside my base.html
<!-- include summernote css/js-->
<link href="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.css" rel="stylesheet">
<script src="http://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.3/summernote.js"></script>
Thanks guys
I'm trying to create a delete view for my product form, my problem is with the submit button, it doesn't delete my object, it just redirects me to previous page.
This a Windows 7 machine, Python 3.7.1, Anaconda 2018.12
I've tried eliminating the line: if request.method == "POST"
And without that line the object is eliminated, so I think the problem is with the if statement or the POST method, but couldn't solve it
views.py:
from django.shortcuts import render, get_object_or_404, redirect
from .forms import ProductForm, RawProductForm
from .models import Product
def product_delete_view(request, id):
obj = get_object_or_404(Product, id=id)
if request.method == "POST":
obj.delete()
return redirect('../')
context = {
"object": obj
}
return render(request, "products\\product_delete.html", context)
product_delete.html:
{% extends 'base.html' %}
{% block try %}
<form action='.' method='POST'>{% csrf_token %}
<h1>Do you want to delete the product "{{ object.title }}"?</h1>
<p>
<input type="submit" value="Yes" />
Cancel
</p>
</form>
{% endblock %}
The idea is that when I click "Yes", the object disappears, but instead I am redirected to the page of the actual object I wanted to delete
I want to build a custom search form. Below is my code. My app is called "viewer". I keep getting a "NameError at /viewer/search/...name 'CustomSearchForm' is not defined". Please help. I know it is a simple error somewhere.
From viewer/urls.py:
from django.conf.urls import *
from viewer import views, forms
from haystack.views import SearchView
urlpatterns = patterns('',
#viewer urls
...
url(r'^search/$', SearchView(form_class=CustomSearchForm), name='haystack_search')
)
From viewer/forms.py:
from django import forms
from haystack.forms import ModelSearchForm
from haystack.query import SearchQuerySet
class CustomSearchForm(ModelSearchForm):
...
Here is the solution I found, using a different approach:
urls.py:
url(r'^search/', 'viewer.views.search'),
views.py:
def search(request):
from .forms import CustomSearchForm
form = CustomSearchForm(request.GET)
searchresults = form.search()
return render(request, 'viewer/search.html', {'form' : form})
in viewer/search.html:
{% extends 'base.html' %}
{% block content %}
<form type="get" action=".">
{{form}}
<button type="submit">Search</button>
</form>
{% endblock %}
Had the same problem but with "NameError at /viewer/search/...name 'SearchForm' is not defined" trying to follow the guide here:
http://django-haystack.readthedocs.io/en/v2.6.0/views_and_forms.html
Just upgrading to Django 1.11.0 did the trick for me. Maybe it would work for you too.