I have been working on a simple forums application for a few weeks now. The main goal of the project is to have sooner written a post and then for the post to be displayed. The project does not utilize user models. For some reason when the user completes the form for their post their post is not displayed. I was wondering if anyone knew why this is happening or if any of y'all have any tips.
views.py
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views import generic
from . import forms
# Create your views here.
class ForumForm(generic.CreateView):
template_name = 'forums_simple/forum.html'
form_class = forms.ForumForm
success_url = '/'
def form_vaild(self, form):
self.object = form.save(commit=False)
self.object.save()
return super().form_vaild(form)
urls.py
from django.contrib import admin
from django.urls import path, include
from . import views
app_name = 'forums'
urlpatterns = [
path('', views.ForumForm.as_view(), name='forum')
]
models.py
from django.db import models
# Create your models here.
class Post(models.Model):
message = models.TextField(blank=True, null=False)
created_at = models.DateTimeField(auto_now=True)
forms.py
from django import forms
from . import models
class ForumForm(forms.ModelForm):
class Meta:
model = models.Post
fields = ('message',)
forum.html
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
{% for message in object_list %}
{{ post.message }}
{% endfor %}
</div>
<div class="container">
<form class="forum_class" action="index.html" method="post">
{% csrf_token %}
{% crispy form %}
<button type="submit" name="big-button"></button>
</form>
</div>
{% endblock %}
You need to add object_list to your context in the view so:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# don't forget to import Post
context['object_list'] = Post.objects.all()
return context
Related
Have serious issues with the following.
have a reviews app in my project where people can read, leave, edit and delete views.
Was all working fine in gitpod on the local side but then when i pushed to Heroku i started getting errors. On Heroku I was gettings a null constraint error and on the local side I was getting "null value in column" error. I cleared my database, deleted users and created a new superuser after updating the models to use uuid instead. Now i'm getting a noreverse error on the local side (god only knows what's going to happen when i push it to Heroku but lets deal with one thing at a time).
Anyways I'll attach all relevant code below.
Have a project due tomorrow so any help would be massively appreciated.
reviews.html
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container-fluid text-white">
<div class="row mt-5">
{% for review in object_list %}
<div class="col col-md-3 reviews">
<h1 class="pt-3">Title: {{ review.title }}</h1>
{% if request.user.is_authenticated %}
{% if user.id == review.user.id %}
Edit
Delete<br>
{% endif %}
{% endif %}
{{ review.review|slice:":50" }}<br>
{{ review.user }}<br>
{{ review.rate }} Stars<br>
{{ review.created_at }}
</div>
{% endfor %}
</div>
<div class="row">
<div class="col">
<a href="{% url 'add_review' %}">
<h1 class="headings">Leave a Review</h1>
</a>
</div>
</div>
</div>
{% endblock %}
models.py
import uuid
from django.db import models
from django.contrib.auth.models import User
RATINGS = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5'),
)
class UserReviews(models.Model):
""" model for user reviews used to create and view reviews """
title = models.CharField(max_length=50, blank=True)
review = models.TextField(max_length=1000)
user = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
rate = models.IntegerField(choices=RATINGS, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
urls.py
from django.urls import path
from .views import ReviewListView, ReviewDetailView, ReviewFormView, UpdateReviewView, DeleteReviewView
urlpatterns = [
path('add_review/', ReviewFormView.as_view(), name='add_review'),
path('', ReviewListView.as_view(), name='reviews'),
path('reviews/<int:pk>', ReviewDetailView.as_view(),
name='reviews_detail'),
path('review/update/<int:pk>', UpdateReviewView.as_view(), name='update_review'),
path('review/<int:pk>/delete/', DeleteReviewView.as_view(), name='delete_review'),
]
views.py
""" imports from django, models.py and forms.py """
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import UserReviews
from .forms import UserReviewForm
class ReviewListView(ListView):
""" view for generating the review list """
model = UserReviews
template_name = "reviews/reviews.html"
ordering = ['-created_at']
class ReviewDetailView(DetailView):
""" view for generation Review Details """
model = UserReviews
template_name = "reviews/reviews_detail.html"
class ReviewFormView(CreateView):
""" view for review form """
model = UserReviews
template_name = "reviews/add_review.html"
form_class = UserReviewForm
success_url = reverse_lazy('reviews')
class UpdateReviewView(UpdateView):
""" view for updating review form """
model = UserReviews
template_name = "reviews/update_review.html"
form_class = UserReviewForm
class DeleteReviewView(DeleteView):
""" view for deleting review form """
model = UserReviews
template_name = "reviews/delete_review.html"
success_url = reverse_lazy('reviews')
forms.py
from django import forms
from .models import UserReviews
class UserReviewForm(forms.ModelForm):
""" meta data to generate contact us form """
class Meta:
""" form model, fields and widgets used"""
model = UserReviews
fields = [
'title', 'review', 'rate'
]
def form_valid(self, form):
# if form is valid return to discussion
form.instance.user = self.request.user
return super().form_valid(form)
I am having a post model with a user having OneToMany Relationship with inbuilt user model for authentication
my urls.py
from django.contrib import admin
from django.urls import path, include
# from views import PostView
from . import views
urlpatterns = [
path('', views.PostView.as_view(), name='blogHome'),
path('post/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
path('post/new/', views.PostCreateView.as_view(), name='post-create'),
path('about/', views.about, name='about')
]
my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
from django.views.generic import (
ListView,
DetailView,
CreateView
)
# Create your views here.
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html')
class PostView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
ordering = ['-date_published']
class PostDetailView(DetailView):
model = Post
class PostCreateView(CreateView):
model = Post
fields = ['title', 'body']
#to add author before validation
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
Post Model
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
body = models.TextField()
date_published = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
I am using post_form.html as the template name
post_form.html
{% extends 'blog/layout.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="content-section p-20">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group p-30">
<legend class="border-bottom mb-4">Create new post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Create</button>
</div>
</form>
</div>
{% endblock %}
I am a beginner in Django , please tell if anything more is needed to solve the problem. Also why this type of error is coming only with Createview and not with other views
Apparently the return of super().form_valid(form) is None and not a valid response. I don't know much of this design pattern in Django but seeing your other methods seems like this view is decorated by some method which returns a valid response. So you should not return something in your implementation. So, drop the return and test again.
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
For some reason, my forms.py doesn't view any of the fields, instead, it only shows the 'Add' button and I don't know what to do anymore. I'd really appreciate if someone who knows what they're doing could tell me what I did, or didn't do.
Please note that I'm new to Django, thank you.
Here's my views.py:
from django.shortcuts import render
from django.utils import timezone
from .models import Measurement
from .forms import MeasurementForm
from django.views import generic
class IndexView(generic.ListView):
model = Measurement
context_object_name = 'measurement_list'
template_name = 'index.html'
queryset = Measurement.objects.all()
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
forms.py:
from django import forms
from .models import Measurement
class MeasurementForm(forms.ModelForm):
class Meta:
model = Measurement
fields = ('measurement_value', 'measurement_unit')
index.html:
{% extends "base.html" %}
{% block content %}
<h1>Climate Measurement Tool</h1>
<h2>Add a new measurement</h2>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save">Add</button>
</form>
<h2>Measurements</h2>
{% if measurement_list %}
<ul>
{% for measurement in measurement_list %}
<li>
<p>{{ measurement }}</p>
</li>
{% endfor %}
</ul>
{% else %}
<p>No measurements yet</p>
{% endif %}
{% endblock %}
The new_measurement() view correctly initializes a form instance and passes it to the template.
Unfortunately, that view is never called.
urls.py defines only one url, handled by IndexView.as_view(), which does not pass a form instance to the template.
I've been trying to display youtube videos by passing the video id in a class and replacing the value in a template.But it doesn't seem to be happening.
My models.py
from django.db import models
class Rockinfo(models.Model):
rock_name = models.CharField(max_length=200,default="ac/dc")
rock_img = models.ImageField(upload_to="%Y/%m/%d",default="1992/08/92")
rank = models.IntegerField(default=0)
def __str__(self):
return self.rock_name
class Rockvids(models.Model):
rockername = models.ForeignKey(Rockinfo)
vid_id = models.CharField(max_length=200,default="Z7JgY9zezj4")
vid_name = models.CharField(max_length=300,default="Something Inside Me")
vid_singer_name = models.CharField(max_length=300,default="Jonathan Reyes Myers")
def __str__(self):
return self.vid_id
my admin.py
from django.contrib import admin
from .models import Rockinfo, Rockvids
class ChoiceInline(admin.TabularInline):
model = Rockvids
extra = 10
class RockinfoAdmin(admin.ModelAdmin):
fieldsets = [
('The Fucking Band', {'fields': ['rock_name']}),
('Image', {'fields': ['rock_img']}),
]
inlines = [ChoiceInline]
list_display = ('rock_name', 'rock_img')
list_filter = ['rank']
search_fields = ['rock_name']
admin.site.register(Rockinfo, RockinfoAdmin)
my application's urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
]
My application's views.py file
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from .models import Rockvids, Rockinfo
class IndexView(generic.ListView):
template_name = 'rockinglist/index.html'
context_object_name = 'latest_rockinfo_list'
def get_queryset(self):
return Rockinfo.objects.order_by('-rank')[:50]
class DetailView(generic.DetailView):
model = Rockinfo
template_name = 'rockinglist/detail.html'
index.html file
{% if latest_rockinfo_list %}
<ul>
{% for rockinfo in latest_rockinfo_list %}
<h1>{{ rockinfo.rock_name }}</a></li>
<img src="img\{{ rockinfo.rock_img }}" alt="ac/dc">
{% endfor %}
</ul>
{% else %}
<p>No</p>
{% endif %}
detail.html file
<h1>{{ rockinfo.rock_name }}</h1>
{% for choice in rockinfo.rockvids_set.all %}
<img id="hide" src="http://img.youtube.com/vi/{{ rockvids.vid_id }}/hqdefault.jpg" data-video="https://www.youtube.com/embed/{{ rockvids.vid_id }}?autoplay=1" width="480" height="300"/>
{% endfor %}
I have been trying to display all the youtube videos once the user clicks on the image by using the videos id passed in Rockvidsclass but there seems to be some error in the loop. Thanks in advance.
In your template loop, you've defined the object as choice. Just refer to it that way rather than using rockvids. See below.
{% for choice in rockinfo.rockvids_set.all %}
<img id="hide" src="http://img.youtube.com/vi/{{ choice.vid_id }}/hqdefault.jpg" data-video="https://www.youtube.com/embed/{{ choice.vid_id }}?autoplay=1" width="480" height="300"/>
{% endfor %}
Since you'll have multiple images, you probably want to change id="hide" to class="hide" as well, since there should only be one element with a given id on a page.