I have used django's models and forms to add a comment section to a blog app, however the form's text field will not show when loaded in the in the browser. Only the submit button loads with no textfield to submit with.
models.py
from django.db import models
from datetime import datetime
from django import forms
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.TextField()
date = models.DateTimeField("date published", default=datetime.now())
def _str_(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('blog.post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=100)
text = models.TextField(max_length=200)
created_date = models.DateTimeField(default=datetime.now())
def _str_ (self):
return self.text
forms.py
from django import forms
from django.forms import ModelForm
from .models import Comment
from django.db import models
class CommentForm(forms.ModelForm):
class Meta:
models = Comment
exclude = ['post']
form = CommentForm
post.html
<div>
<div class="container">
<h5>New comment</h5>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<br>
<button class="btn" style="background-color:lightblue" type="submit">Submit Comment</button>
</form>
</div>
</div>
views.py
from django.shortcuts import render
from django.views import generic
from .forms import CommentForm
from .models import Comment
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('/blog/<int:pk>', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/post.html', {"form":form})
form = CommentForm(request.POST)
form = CommentForm()
In django's admin i can add new comments and the form loads as expected there but does not work on the blog post itself. Admin submitted comments through the admin panel are also saving and displaying fine.
you have a typo in forms.py
change models to model
from django import forms
from django.forms import ModelForm
from .models import Comment
from django.db import models
class CommentForm(forms.ModelForm):
class Meta:
model = Comment # changed from models
exclude = ['post']
in views.py
you are missing imports
from django.shortcuts import get_object_or_404,redirect
from .models import Post
other changes
in your models.py
the to string method for classes is __str__ not _str_
with this changes i was able to reproduce this django project with your snippets that works in posting comments
Related
I am new to the community. I usually am able to just find my answer, but I have been searching and searching, and can't seem to find anything similar to what I've got going on. I have a ModelForm set up to register new users. I got it to work, and send information over to the sqlite database. However, when I try to log the newly registered user in it says:
"Please enter a correct username and password. Note that both fields may be case-sensitive."
login.html:
{% extends 'app/register.html' %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Login">
</form>
Back to Homepage
<br>
Reset password
<br>
Register
{% endblock %}
views.py
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.decorators import login_required
from datetime import datetime
from django.http import HttpRequest
from django.shortcuts import render, redirect
from django.urls import reverse
from . import forms
from django.contrib import auth
def index(request):
"""Renders the home page."""
assert isinstance(request, HttpRequest)
return render(
request,
'app/index.html',
{
'title':'Home Page',
'year':datetime.now().year,
}
)
def register(request):
if request.method == "GET":
form = forms.Registration(request.GET)
return render(
request, "app/register.html",
{"form": form}
)
elif request.method == "POST":
form = forms.Registration(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect(reverse("index"))
models.py
from django.contrib.auth.models import User
from django.db import models
# Create your models here.
class Patient(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
#birthdate = models.DateField(auto_now=False, null=True, blank=True)
gender = models.CharField(max_length=100, blank=True)
allergies = models.TextField(blank=True)
email = models.CharField(max_length=200)
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
last_login = models.CharField(max_length=100)
and forms.py:
from django import forms
from . import models
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
class Registration(forms.ModelForm):
class Meta:
model = models.Patient
fields = ('first_name','last_name', 'gender', 'email', 'username', 'password', 'allergies',)
any help would be greatly appreciated. Please forgive me if I've left something out, just let me know. Thank you!
In line 33 in the views file you used auth_login() function but I could not find where you imported it
did you mean authentication() or login() functions?
So after a lot of trial and error and fiddling, I ultimately fixed it this way, thanks to Abdul Aziz Barkat's suggestion above.
I changed Patient(models.Model) to Patient(AbstractUser)
And then I also had to change the Registration(forms.ModelForm) to Registration(UserCreationForm). All of the users are authenticating just fine now, thank you!
What I want to do: I want to have a login form that when details are entered they are saved on the admin side.
My problem: the forms are not showing up on my local host page. See image below:
Here is the code from the login form app:
admin.py:
from django.contrib import admin
# Register your models here.
from .models import Contact
admin.site.register(Contact)
from apps.py:
from django.apps import AppConfig
class ContactConfig(AppConfig):
name = 'contact'
from forms.py
from .models import Contact
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ('username', 'password')
from models.py:
class Contact(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(
max_length=100,
)
def __str__(self):
return f'{self.username} {self.password}'
from views.py:
# Create your views here.
from .forms import ContactForm
def contact(request):
template = "home2.html"
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
form.save()
else:
form = ContactForm()
context = {
'form': form,
}
return render(request, template, context)
Then finally from the login page:
{% load static %}
<form method="post" class="form">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn">Log In</button>
</form>
Another thing: forms are connected to the admin side but just do not appear on the login page
I looked at similar questions but they do not seem to apply. I have a very simple django form which does not show on the website, I only see the Submit button. Here are the relevant files:
models.py
from django.db import models
from django.urls import reverse
import uuid
# Create your models here.
class Job(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
job_name = models.CharField(max_length=200)
#One to many relationship requires on_delete
email = models.EmailField()
def __str__(self):
return self.job_name
forms.py
from django import forms
class JobForm(forms.Form):
job_name = forms.CharField(max_length=200)
email = forms.EmailField()
views.py
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import JobForm
from .models import Job
class HomePageView(TemplateView):
template_name = 'index.html'
class SubmitPageView(TemplateView):
template_name = 'submit.html'
def submit_job(request):
# Retrieve post by id
if request.method == 'POST':
# Form was submitted
form = JobForm(request.POST)
if form.is_valid():
#Form fields passed validation
#If the form is valid, we retrieve the validated data accessing
#form.cleaned_data. This attribute is a dictionary of form fields and their values.
cd = form.cleaned_data
my_model = Job()
my_model.job_name = cd.get('job_name')
my_model.email = cd.get('email')
# Save the job to the database
my_model.save()
else:
form = JobForm()
return render(request, SubmitPageView(), {'form': form})
And in my template I have
<form method="POST" action=".">
<table>
{% csrf_token %}
{{ form.as_table }}
</table>
which gets rendered as:
<form method="POST" action=".">
<table>
<input type="hidden" name="csrfmiddlewaretoken" value="I7yL9XAUhEPiriKVHKtqh9UfhsLWoJrBo68uguqMecX8gmuNoJV7gykvsPc7FtQ2">
</table>
OK, I found the solution by following https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/
Basically, as I was using class-based views, the functions to get and post the form need to be subsumed into the class-based view for that page. Here is the current version
of views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import JobForm
from .models import Job
class HomePageView(TemplateView):
template_name = 'index.html'
class SubmitPageView(TemplateView):
form_class = JobForm
template_name = 'submit.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
#Form fields passed validation
#If the form is valid, we retrieve the validated data accessing
#form.cleaned_data. This attribute is a dictionary of form fields and their values.
cd = form.cleaned_data
my_model = Job()
my_model.job_name = cd.get('job_name')
my_model.email = cd.get('email')
# Save the job to the database
my_model.save()
else:
form = JobForm()
return render(request, self.template_name, {'form': form})
Try code below:
# if a GET (or any other method) we'll create a blank form
else:
form = JobForm()
return render(request, 'submit.html', {'form': form})
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="Submit">
</form>
Does it make a difference if you define the form as a modelForm and explicitly state the model and fields?
Add/modify the following to your Forms.py:
class JobForm(forms.ModelForm):
class Meta:
model = Job
fields = ('job_name', 'email')
job_name = forms....
I have a model called Post. The data in Post is displayed to every user while I want this to be user specific.
I'm new to Django. This app is created following the Django for Girls tutorial. I later added support for user registration.
models.py:
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
Example from views.py:
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from .models import Post
from .forms import PostForm
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
#login_required
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})
Example from the template (post_list.html):
{% for post in posts %}
<div class="post">
<div class="date">
<p>published: {{ post.published_date }}</p>
</div>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaksbr }}</p>
</div>
{% endfor %}
Change your filter to filter by user as well as published_date:
posts = Post.objects.filter(
published_date__lte=timezone.now(),
author=request.user
).order_by('published_date')
Inside your class/function view check if the user is authenticated.
if not request.user.is_superuser:
raise Http404
Also check this
My view is a function based view (it is a legacy and due to inline formset usage it is easier to keep it that way, rather than CBV). My goal is to be able to render the ModelForm for the model object Article.objects.get(user=user).latest("id") and with the POST method, update the same object that has been rendered. The issue is that the ModelForm "does not remember" the object it corresponded to. What would be the right way to pass that info about the object to the view for use in the POST method?
Below is the simplified version of the views.py and the urls.py
views.py
from django.contrib.auth.models import User
from django.shortcuts import render_to_response
from django.template import RequestContext
from specify.models import Article
from specify.forms import ArticleForm
def index(request):
user = User.objects.get(username=request.user.username)
if request.method == "POST":
a_form = ArticleForm(request.POST, instance= *???* )
a_form.save()
else:
a = Article.objects.get(user=user).latest("id")
a_form = ArticleForm(instance=a)
return render_to_response(
"specify/index.html",
{
"a_form" : a_form,
},
context_instance=RequestContext(request)
)
urls.py
from django.conf.urls import patterns, url
from specify import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index')
)
EDIT1: added models.py and forms.py
models.py
from django.db import models
class Article(models.Model):
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
forms.py
from django.forms import ModelForm
from specify.models import Article
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['pub_date', 'headline', 'content']
First you should pass article id to the template, in view.py
def index(request):
user = User.objects.get(username=request.user.username)
if request.method == "POST":
#Explained later
else:
a = Article.objects.get(user=user).latest("id")
a_form = ArticleForm(instance=a)
article_id = a.id
return render_to_response(
"specify/index.html",
{
"a_form" : a_form,
"article_id": article_id,
},
context_instance=RequestContext(request)
)
Second in your template inside of your form html element you should handle your article id
{% if article_id %}
<input type="hidden" value='{{ article_id }}' id='article_id' name='article_id'/>
{% endif %}
Thirdly in update handling you should do following:
if request.method == "POST":
article_id = request.POST.get('article_id') # You are getting passed article id
a = Article.objects.get(pk=article_id) # You are getting instance by id
a_form = ArticleForm(request.POST, instance=a)
a_form.save()
Try above steps and if you have problem leave a comment