I have been working on a blog site using django and I made a way to add post within the home page without going to the admin page but when I post using the new way I get this error
This is my models.py file
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag = models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField(max_length=3500)
def __str__(self):
return (self.title + " | " + str(self.author))
def get_absolute_url(self):
return reverse("article-view", args=(str(self.id)))
This is the views.py file
from django.views.generic import ListView, DetailView, CreateView
from .models import Post
class HomeView(ListView):
model = Post
template_name = "home.html"
class ArticleDetailView(DetailView):
model = Post
template_name = "detail_view.html"
class AddPostView(CreateView):
model = Post
template_name = "add_post.html"
fields = "__all__"
This is the polls/urls.py
from django.urls import path
from .views import HomeView, ArticleDetailView, AddPostView
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article-view'),
path('add_post/', AddPostView.as_view(), name='add_post'),
]
This is the add_post.html file
{% extends 'base.html' %}
{% block content %}
<head>
<title>Adding Post</title>
</head>
<h1>Add Blog Posts</h1>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-secondary">Post</button>
</form>
{% endblock %}
Thank you.
Okay, so it looks like this is caused by the model's get_absolute_url reverse args=(). I changed the below code in models.py from:
def get_absolute_url(self):
return reverse("article-view", args=(str(self.id)))
Into
def get_absolute_url(self):
return reverse("article-view", args=[self.id])
The problem seems to be args=(), it is iterating over the str(self.id). So id=10 would actually be returned as a tuple (1,0). I also removed the str() around the self.id since the URL takes in an int.
Related
Can someone help me to solve this error?
ValueError at /create_entry/
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x000000B7BBF1BFC8>>": "Entry.entry_author" must be a "User" instance.
urls.py
from django.urls import path
from .views import HomeView, EntryView, CreateEntryView
urlpatterns = [
path('', HomeView.as_view(), name = 'blog-home'),
path('entry/<int:pk>/', EntryView.as_view(), name = 'entry-detail'),
path('create_entry/', CreateEntryView.as_view(success_url='/'), name = 'create_entry')
]
views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView, CreateView
from .models import Entry
class HomeView(ListView):
model = Entry
template_name = 'entries/index.html'
context_object_name = "blog_entries"
class EntryView(DetailView):
model = Entry
template_name = 'entries/entry_detail.html'
class CreateEntryView(CreateView):
model = Entry
template_name = 'entries/create_entry.html'
fields = ['entry_title', 'entry_text']
def form_valid(self,form):
form.instance.entry_author = self.request.user
return super().form_valid(form)
models.py
from django.db import models
from django.contrib.auth.models import User
class Entry(models.Model):
entry_title=models.CharField(max_length=50)
entry_text=models.TextField()
entry_date=models.DateTimeField(auto_now_add=True)
entry_author=models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = "entries"
def __str__(self):
return f'{self.entry_title}'
create_entry.html
{% extends "entries/base.html" %}
{% block content %}
<div class="col-md-8"><br><br>
<!-- Blog Post -->
<div class="card mb-4">
<div class="card-header">
Create Blog Post
</div>
<div class="card-body">
<form class="form-conrol" action="" method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn btn-primary">Post Entry</button>
</form>
</div>
</div>
</div>
{% endblock %}
I need your help for this
small project.
You are not logged in, so self.request.user is not a real user. You can use the LoginRequiredMixin [Django-doc] to restrict access to a view such that you can only post (and retrieve) the view when the user has logged in:
from django.contrib.auth.mixins import LoginRequiredMixin
class CreateEntryView(LoginRequiredMixin, CreateView):
model = Entry
template_name = 'entries/create_entry.html'
fields = ['entry_title', 'entry_text']
def form_valid(self,form):
form.instance.entry_author = self.request.user
return super().form_valid(form)
models.py
from django.db import models
class Profile(models.Model):
name=models.CharField(max_length=20 )
age=models.IntegerField()
def __str__(self):
return self.name
class Like(models.Model):
user=models.ForeignKey(Profile,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
like=models.IntegerField(default=0)
def __str__(self):
return self.choice_text
views.py
from django.shortcuts import render
from .models import Profile, Like
# Create your views here.
def index(request):
all_name=Profile.objects.all()
context={'all_name':all_name}
return render(request, 'database/index.html',context)
def detail(request, profile_id):
all_likes=Like.objects.get(pk=profile_id)
return render(request, 'database/detail.html', {'all_likes':all_likes})
index.html
<h1>hey</h1>
{% for name in all_name %}
<li>{{ name.name }}</li>
{% endfor %}
detail.html
{{all_likes}}
urls.py
from django.urls import path
from . import views
app_name='database'
urlpatterns = [
path('index/', views.index, name='index'),
path('<int:profile_id>/', views.detail, name='detail'),
]
now http://127.0.0.1:8000/database/index/ produces two list item,
but when I click on both, i am redirecting to http://127.0.0.1:8000/database/1/ .
http://127.0.0.1:8000/database/2/ is working manually but not when I click. Couldn't figure out the error in the code.
You pass all objects to HTML:
all_name = Profile.objects.all()
and on for loop in HTML you used
{% for name in all_name %}
Here:
<li>{{ name.name }}</li>
you are using user.id instead of name.id.
Use:
<li>{{ name.name }}</li>
Then it will use the id of the object in for loop and will hit the correct URL.
I have a books app using a UUID with a listview of all books and detailview of individual books. I keep getting the following error message:
NoReverseMatch at /books/
Reverse for 'book_detail' with arguments '('/books/71fcfae7-bf2d-41b0-abc8-c6773930a44c',)' not found. 1 pattern(s) tried: ['books/(?P<pk>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$']
Here is the models.py file:
# books/models.py
import uuid
from django.db import models
from django.urls import reverse
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('book_detail', args=[str(self.id)])
The urls.py file where I'm using to convert the id from the model to a uuid.
# books/urls.py
from django.urls import path
from .views import BookListView, BookDetailView
urlpatterns = [
path('', BookListView.as_view(), name='book_list'),
path('<uuid:pk>', BookDetailView.as_view(), name='book_detail'),
]
The top-level urls.py file looks like this and adds a books/ route.
# urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', include('books.urls')),
The views.py file:
from django.views.generic import ListView, DetailView
from .models import Book
class BookListView(ListView):
model = Book
context_object_name = 'book_list'
template_name = 'books/book_list.html'
class BookDetailView(DetailView):
model = Book
context_object_name = 'book'
template_name = 'books/book_detail.html'
And the relevant templates file.
<!-- templates/book_detail.html -->
{% extends '_base.html' %}
{% block content %}
{% for book in book_list %}
<div>
<h2>{{ book.title }}</h2>
</div>
{% endfor %}
{% endblock content %}
I believe I'm implementing this correctly but the URL is not liking my UUID. What is amiss?
The problem is not "adding uuid". The problem is that you are doing the URL reversal twice: once in get_absolute_url and once in the {% url %} tag. Use one or the other, not both.
Either:
{{ book.title }}
Or:
{{ book.title }}
I'm writing a small chat programm in Django but have problems getting any further.
Here's the code:
models.py
from django.db import models
from datetime import datetime
from django.utils import timezone
class Chat(models.Model):
chatname = models.CharField(max_length=100)
description = models.TextField()
created_at = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.chatname
class Comment(models.Model):
chat = models.ForeignKey(Chat, on_delete=models.CASCADE)
commenter = models.CharField(max_length=30)
comment = models.TextField()
created_at = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.comment
urls.py
from django.conf.urls import url
from . import views
from django.views.generic import ListView
from chat.views import CommentList
app_name = 'chats'
urlpatterns = [
url(r'^$', views.index, name="index"),
url(r'^comments/(?P<pk>[0-9]+)/$', views.CommentList.as_view(), name='comments'),
]
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth import authenticate, login
from django.views import generic
from .models import Chat, Comment
def index(request):
username = None
if request.user.is_authenticated():
username = request.user.username
chats = Chat.objects.all()[:10]
context = {
'chats':chats
}
return render(request, 'chat/index.html', context)
class CommentList(generic.ListView):
queryset = Comment.objects.filter(chat_id=1)
context_object_name = 'comments'
My comment_list.html
{% extends "chat/base.html" %}
{% block content %}
Go back
<h3>Comments</h3>
<h2>{{chat.id}}</h2>
<ul>
{% for comment in comments %}
<li>{{ comment.commenter }}: {{ comment.comment }}</li>
{% endfor %}
</ul>
{% endblock %}
My database structure contains these two models: Chat and Comment. Each chat(room) is supposed to have its own comments. I used 'models.ForeignKey' to be able to filter the comments for each chat(room). In my index.html I list all the chats and each of these has a hyperlink to the /comments/ section.
In my views.py I have this line: 'queryset = Comment.objects.filter(chat_id=1)'
Chat_id is the column in the comments sql table and as it is now it will only show comments that belong to the chat with pk=1. How can I auto access the chat for the different urls /comments/1/ /comments/2/ and so on..?
Hope the explanation is clear. Sorry beginner here, I can try to explain further if it doesn't make a lot of sense.
Best,
Fabian
You should define the get_queryset method instead of the standalone queryset attribute.
def get_queryset(self, *args, **kwargs):
return Comment.objects.filter(chat_id=self.kwargs['pk'])
Instead of CommentList you can use plain view:
def comments_index(request, chatid):
return render(request, 'xxx/comment_list.html', {
'comments': Comment.objects.filter(chat_id=chatid)
})
And in urls:
url(r'^comments/(?P<chatid>[0-9]+)/$', views.comments_index, name='comments'),
I have a project where I wish to upload an image with the Django auto generated class-based views, and it works on the admin side, but I don't know what I'm missing to make it work from an HTML page. I've searched the web with a little luck or not enough clarification.
So maybe someone can tell me what I'm missing. Here is my code:
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'project/app/media_cdn')
models.py
from django.db import models
from django.core.urlresolvers import reverse
class Article(models.Model):
title = models.CharField(max_length = 200)
...
thumbnail = models.FileField(null = True, blank = True)
...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles_detail', kwargs={'pk': self.pk})
class Meta:
ordering = ['-pk']
views.py
from django.shortcuts import render
from app.models import Article
from django.views.generic import *
from django.core.urlresolvers import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
# Create your views here.
def index(request):
return render(request, 'index.html')
class ArticleList(ListView):
model = Article
class ArticleDetail(DetailView):
model = Article
class ArticleCreate(LoginRequiredMixin, CreateView):
model = Article
fields = ['title', 'description', 'abstract', 'thumbnail', 'author', 'category', 'publishDate']
class ArticleUpdate(LoginRequiredMixin, UpdateView):
model = Article
fields = ['title', ..., 'thumbnail', ...]
class ArticleDelete(LoginRequiredMixin, DeleteView):
model = Article
success_url = reverse_lazy('articles_list')
urls.py
from django.conf.urls import url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from app import views, auth
urlpatterns = [
url(r'^admin/',admin.site.urls),
...
url(r'^articles/(?P<pk>[0-9]+)/$', views.ArticleDetail.as_view(), name = 'articles_detail'),
url(r'^articles/create/$', views.ArticleCreate.as_view(), name = 'articles_create'),
url(r'^articles/update/(?P<pk>[0-9]+)/$', views.ArticleUpdate.as_view(), name = 'articles_update'),
url(r'^articles/delete/(?P<pk>[0-9]+)/$', views.ArticleDelete.as_view(), name = 'articles_delete'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
article_form.html
{% extends 'layout.html' %}
{% block content %}
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
As much as I was able to gather, I managed to follow all the steps but I still can't get the thumbnail to update when uploading from articles/create/ and articles/update/.../
Thanks in advance.