How to output Django form on the browser - python

I'm learning to create a post and comment session with Django and I'm following a tutorial but I don't know why I'm not getting the same result as the one in the tutorial. The post aspect is working but the form for comments is not being displayed on the browser. Even after going through Django documentation and other resources online, I still don't see where I'm getting it wrong. I have the following directories and files:
start is my app directory while education is the main django directory
start/models.py
class Comment (models.Model):
post = models.ForeignKey(Post,related_name = 'comments', on_delete = models.CASCADE)
name = models.CharField()
email = models.Email()
body = models.TextField()
createdAt = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['createdAt']
start/forms.py
from django import forms
from .models import Comment
class post_comment(forms.ModelForm):
class Meta:
model = Comment
fields = ['name', 'email', 'body']
start/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .forms import post_comment
def fullPost(request, slug):
post = Post.object.all()
return render (request, 'start/start.html', {'post': post})
if request.method == 'POST':
form = post_comment(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect ('fullPost', slug=post.slug)
else:
form = post_comment()
return render (request, 'start/fullPage.html', {'post': post, 'form': form})
start/templates/start/fullpost.html
•••
<h3>Comment</h3>
<form method = 'post' action = '.'>
{% csrf_token %}
{{ form.as_p }}
<button> Post comment </button>
</form>

The issue is with the structure of the fullpost view
In this line:
return render (request, 'start/start.html', {'post': post})
the function is exited without the form.
You could try:
start/views.py
...
def fullPost(request, slug):
post = Post.object.all()
#return render (request, 'start/start.html', {'post': post})
if request.method == 'POST':
form = post_comment(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect ('fullPost', slug=post.slug)
else:
form = post_comment()
return render (request, 'start/fullPage.html', {'post': post, 'form': form})
...
If form.is_valid() fails, it will fall through to the end, rendering the form with the incorrect data.
Edit
Since you are learning , the following line may be wrong
post = Post.object.all()
because objects.all() retrieves all the posts in the db. Unless you want to comment all posts, you may need to rewrite it as follows:
post=Post.objects.get(slug=slug)
This will retrieve the post with the matching slug, assuming the slug field is unique.
https://docs.djangoproject.com/en/3.1/topics/db/queries/#retrieving-all-objects
https://docs.djangoproject.com/en/3.1/topics/db/queries/#retrieving-a-single-object-with-get

Related

Django forms: cannot access local variable 'form' where it is not associated with a value

Condition: I have a model, created an empty table in the database, and I'm trying to create an html form that will fill in the fields of the corresponding columns of the table.
And here's what my app looks like:
models.py
from django.db import models
class Cities(models.Model):
city = models.CharField(max_length=100)
def __str__(self):
return self.state
class Routes(models.Model):
route_name = models.CharField(max_length=50, default='Route')
lvl = models.IntegerField(default=0)
about = models.TextField(max_length=1500)
total_distance = models.IntegerField(default=0)
city = models.ForeignKey(Cities, on_delete=models.CASCADE)
forms.py
from django.forms import ModelForm
from .models import Routes
class RouteForm(ModelForm):
class Meta:
model = Routes
fields = '__all__'
views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse
from routes_form.forms import RouteForm
def getAbout(request):
if request.method == 'POST':
form = RouteForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'routes_form/form_page.html', {'form': form})
form.html
<form method="post">
{% csrf_token %}
<legend>
<h2>About</h2>
</legend>
{{ form }}
<input type="text" placeholder="Write more about the route: about waypoints, points of interest and warnings.">
<input type="submit" value="Send route">
</form>
I have already tried to do everything as indicated in the Django Forms documentation. But still something is wrong. Even at the moment of starting the server, it writes an error:
cannot access local variable 'form' where it is not associated with a value
It is because you haven't defined form for GET method so:
def getAbout(request):
if request.method == 'POST':
form = RouteForm(request.POST)
if form.is_valid():
form.save()
return redirect('some_view_name_to_redirect')
else:
form=RouteForm()
return render(request, 'routes_form/form_page.html', {'form': form})
Note: Models in Django are written in singular form, as Django itself add s as the suffix, so it is better to name the models as City and Route.
Here you passed form = RouteForm(request.POST) object for POST request you need to pass for GET request so, when def getAbout(request) function called with GET request then renders it like this ...
def getAbout(request):
form=RouteForm() # <---- called at GET request
if request.method == 'POST':
form = RouteForm(request.POST) # <---- called at POST request
if form.is_valid():
form.save()
return redirect("/")
return render(request, 'routes_form/form_page.html', {'form': form})

Images Along With Post Only Applying In Django Admin and Not Regular Form

Like the title says, I'm trying to create a social media app and my users can upload text to their websites. Currently I'm working on adding Image functionality. I can easily add this images in the Django admin page, but whenever I try to do it from the User's create post form, nothing shows up. Here's my post create form:
{% extends "social/base.html" %}
{% load crispy_forms_tags %}
{% block content4 %}
<h1>Make Your Post</h1>
<p>Write a post / Share an image</p>
<br>
<div class="container">
<form method="post">
{% csrf_token %}
{{form|crispy}}
<button type="submit" name="button">Make Post</button>
</form>
</div>
{% endblock content4 %}
Here's my views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Posts
from django.contrib.auth.forms import AuthenticationForm
from .forms import NewUserForm
from django.contrib import messages
from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
from django.contrib.auth.decorators import login_required
# Create your views here.
def home(request):
context = {
'posts' : Posts.objects.all()
}
return render(request, 'social/social.html', context)
def register(request):
if request.method == "POST":
form = NewUserForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.success(request, f"New Account Created: {username}")
login(request, user)
return redirect ("/social")
else:
for msg in form.error_messages:
print(form.error_messages[msg])
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request, 'social/register.html', {"form" : form})
form = NewUserForm
return render(request, 'social/register.html', {"form" : form})
def logout_request(request):
logout(request)
messages.info(request, "Logged out successfully!")
return redirect('/social')
def login_request(request):
if request.method == 'POST':
form = AuthenticationForm(request, data = request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username = username, password = password)
if user is not None:
login(request, user)
messages.info(request, f"You are now logged in as {username}")
return redirect ('/social')
else:
messages.error(request, "Invalid username and/or password.")
else:
messages.error(request, "Invalid username and/or password.")
form = AuthenticationForm()
return render(request, 'social/login.html', {'form' : form})
class PostCreateView(CreateView):
model = Posts
fields = ['post_title', 'post_text_content', 'post_image']
def form_valid(self, form):
form.instance.post_author = self.request.user
print(self.request.user)
return super().form_valid(form)
my model:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class Posts(models.Model):
post_title = models.CharField(max_length = 40, help_text = 'Enter post title')
post_text_content = models.TextField(max_length = 1000)
post_author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
post_date = models.DateField(auto_now = True, auto_now_add = False)
#Make optional Image Field
post_image = models.ImageField(upload_to = 'images', blank = True)
class Meta:
ordering = ['-post_date', 'post_title', 'post_author', 'post_text_content', 'post_image']
def __str__(self):
return self.post_title
def get_absolute_url(self):
return reverse('social-home')
That's pretty much it. If you need any more code, please ask me.
Thank you in advance!
EDIT: To be clear, when I add the images from the admin "create new post" it works, but when I add the image from the regular django form it does not show up.
You need to set enctype="multipart/form-data" on your form tag in you HTML to upload files.
<form method="post" enctype="multipart/form-data">

"Post.user" must be a "User" instance

I am new to using django and I'm creating a simple webpage that takes in user input and saves it to the Model Form
models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
post = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
from django import forms
from .models import Post
class HomeForm(forms.ModelForm):
post = forms.CharField()
class Meta:
model = Post
fields = ('post',)
views.py
from django.shortcuts import render, redirect
# Create your views here.
from django.http import HttpResponse
from django.views.generic import TemplateView
from .forms import HomeForm
class HomeView(TemplateView):
template_name = 'home.html'
def get(self, request):
form = HomeForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = HomeForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
text = form.cleaned_data['post']
form = HomeForm()
return redirect('home.html')
args = {'form': form, 'text': text}
return render(request, self.template_name, args)
home.html
{% block body %}
<div class ='container'>
<h1>Home</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type ='submit'>Submit</button>
</form>
</div>
{% endblock %}
When I run the server the webpage comes up normal but when I type in some input an error page pops up and says : ValueError at /
Cannot assign ">": "Post.user" must be a "User" instance.
Any Help would be appreciated!

How to create a video blog with Django?

I am learning Django. I have started with Django girls blog tutorial which is very basic. Now I want to convert this with the conceptual video blog where user can upload a video like Youtube and user will be able to play that video on the page blog. Besides, I want every post will be moderated by admin. Can anyone expert help me with some coding suggestion as I am newcomer? I have included the completed code bellow.
#ALL MODELS
from django.conf import settings
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
###############################################################
# ALL VIEWS
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post
from django.utils import timezone
from .forms import PostForm
def post_list(request):
posts = Post.objects.filter(
published_date__lte=timezone.now(
)).order_by('-published_date')
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})
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
# post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
# post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
###################################################################
# URL patterns
from django.urls import path
from . import views
urlpatterns = [
path('', views.post_list, name='post_list'),
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/new/', views.post_new, name='post_new'),
path('post/<int:pk>/edit/', views.post_edit, name='post_edit'),
]
#################################################################
# Forms
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text',)
Guys I have solved my problem on my own. I have added just a simple code inside the video tag of html5. I have provided the code bellow.
Code for model:
from django.db import models
class VideoUploader(models.Model):
title = models.CharField(max_length = 100)
clip = models.FileField(upload_to='videos/%Y/%m/%d/')
description = models.TextField()
def __str__(self):
return self.title
HTML5 post list page:
{% block content %}
<div class="post">
<h2>{{ post.title }}</h2>
<video src="{{ post.clip.url }}" controls controlsList="nodownload"
width="640" height="480"></video>
<p>{{ post.description }}</p>
</div>
{% endblock %}

(HELP) Django Model Form does not recognize Image file

I created a Form using one of my models i.e (Post), for my blog website. The form is meant for writers to post articles. In that form there is an Image attribute where the writer can upload an image. However, when i try to upload an image and post it, i get a feedback saying "field required", i think the form is not recognizing the image am trying to upload onto the the database. please help:
this is the form view from views.py:
def formview(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return render(request, 'form.html', {'form':form})
this is from forms.py:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
image = forms.FileField
class Meta:
model = Post
fields = ['category', 'title', 'body', 'image', 'author']
this from my models.py:
class Post(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=100)
pub_date = models.DateTimeField(auto_now_add=True)
body = models.TextField()
image = models.FileField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.IntegerField(default=1)
def __str__(self):
return self.title
this is my forms.html template:
<form method="POST" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Post</button>
this is my urls.py:
from django.conf.urls import url
from . import views
app_name = 'posts'
urlpatterns = [
url(r'^$', views.homeview, name='homeview'),
url(r'^(?P<pk>[0-9]+)$', views.postview, name='postview'),
url(r'^category/(?P<pk>[a-zA-Z0-9]+)/$', views.categoryview,
name='categoryview'),
url(r'^author/(?P<pk>[a-zA-Z0-9]+)/$', views.authorview, name='authorview'),
url(r'^add_post/$', views.formview, name='formview'),
]
these are the pics might help explain what am trying to say:
Filling the form and selecting the picture
Error message after trying to post
Thank you
def formview(request):
if request.method == 'POST':
form = PostForm(request.POST,request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
else:
form = PostForm()
return render(request, 'form.html', {'form':form})
this form = PostForm(request.POST,request.FILES),you need add FILES to PostForm

Categories