I´m making my own portfolio and I wanna be able to see the messages that people sent me in the admin page but I don't seem to be able to make it so when someone submits the message it saves in the model and "broadcasts" in the admin page.
Models.py
from django.db import models
# Create your models here.
class Messages(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=50)
website = models.CharField(max_length=50)
text = models.CharField(max_length=500)
Forms.py
from django import forms
from django.core import validators
from django.forms import ModelForm
from .models import Messages
class Messages(forms.ModelForm):
name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'name'}), required=True, label='', max_length=100)
email = forms.EmailField(widget=forms.TextInput(attrs={'class' : 'email'}), required=True, label='', max_length=50)
website = forms.CharField(widget=forms.TextInput(attrs={'class' : 'website'}),required=False, label='', max_length=50)
text = forms.CharField(widget=forms.TextInput(attrs={'class' : 'text'}), required=True, label='', max_length=500)
bot = forms.CharField(required=False, widget=forms.HiddenInput, validators=[validators.MaxLengthValidator(0)])
class Meta():
model = Messages
fields = '__all__'
Views.py
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseNotFound
from django.template import Template, Context
from . import forms
# Create your views here.
def index(request):
return render(request, 'index.html')
def portfolio(request):
return render(request, 'portfolio.html')
def certificate(request):
return render(request, 'certificate.html')
def contact(request):
form = forms.Messages()
if request.method == 'post':
form = form.Messages(request.post)
if form.is_valid():
form.save(commit=True)
return thankyou(request)
else:
print('CONTACT ERROR')
return render(request, 'contact.html', {'form':form})
def thankyou(request):
return render(request, 'thankyou.html')
Admin.py
from django.contrib import admin
from toni.models import Messages
# Register your models here.
admin.site.register(Messages)
Python is case sensitive. The request.method will always be uppercase, and the post data is stored in request.POST. Change the code to:
if request.method == 'POST':
form = forms.Messages(request.POST)
You can debug problems like this by adding more print() lines. For example, you could have added print("in the post") after if request.method == 'post':. Then when you saw that the line was never printed, you could have added print(request.method). Hopefully you would then spot the mismatch between 'post' and 'POST'.
Related
I am trying to build up a posting webpage.
This is how it works:
you click a button, the posting form will appear, you fill in the form, you click the submit button, and the process is complete. And when the form is submitted, a url parameter will be passed as the value of a hidden input in the modelform in the views.py.
However, when I browse the model in manage.py shell, None is saved instead of the url parameter.
Here are the codes:
models.py
from django.db import models
from django.db.models import CharField, TextField, DateField
class Post(models.Model):
username = CharField(max_length=30, blank=True, null=True)
content = TextField()
dt_created = DateField(auto_now_add=True)
dt_modified = DateField(auto_now=True)
def __str__(self):
return self.username
forms.py
from django import forms
from django.forms import Textarea, HiddenInput
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['content', 'username']
widgets = {
'content': Textarea(attrs={
'class': 'write_input',
'placeholder': 'write your story here...'
}),
'username': HiddenInput(attrs={
'value': ' '
})
}
labels = {
'content': ''
}
urls.py
from django.urls import path, include
from . import views
urlpatterns = [
path('<str:username>/main/', views.account_main, name='account_main')
]
views.py
from django.shortcuts import render, redirect
from .forms import PostForm
from .models import Post
def account_main(request, username):
context = dict()
if request.method == 'POST':
form = PostForm(request.POST, initial={'username': username})
if form.is_valid():
form.save()
return redirect('account_main', username=username)
form = PostForm()
posts = Post.objects.all().order_by('dt_created')
context['username'] = username
context['form'] = form
context['posts'] = posts
return render(request, 'Account/account_main.html', context=context)
What I have tried:
Passing initial={'username': username} as kwargs to PostForm(),
Accessing cleaned_data and passing the url parameter as value like: form.cleaned_data['username'] = username
I could not find any solution for the issue in Google or Stack Overflow so far. Thank you in advacnce for your answer!!
I found the solution.
After form.is_valid() returns True, I save the form by form = form.save(commit=False).
Then, I pass the url parameter as the value for form.username. Finally, I save the form by form.save().
When I browse the model, the url parameter is saved well as the username value.
Here is the code after I modified it:
def account_main(request, username):
context = dict()
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.username = username
form.save()
return redirect('account_main', username=username)
If your main motive is to pass a hidden field along with a form you can directly send without including it in the URL.
And you can get files by
-->request.POST.get(#fieldName)
So I am building a to do app in Django. I have created databases for the users and todo items. But I have a problem, how can each user have its own data. Like every user should add their own data. It seems like there is no answer out there.
My models.py
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
My forms.py
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username','email','password1','password2']
So how can I connect those both. I have red that I have to use foreign key. But I really don't understand how I can do it
You specify a ForeignKey [Django-doc] in the Task model that refers to the user that constructed it:
# app/models.py
from django.db import models
from django.conf import settings
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.title
You can then make a ModelForm where you exclude the user. For example:
# app/forms.py
from django import forms
from app.models import Task
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ['user']
Then in the view we can "inject" the user in the instance we create, for example:
# app/views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from app.forms import TaskForm
#login_required
def create_task(request):
if request.method == 'POST':
form = TaskForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('name-of-some-view')
else:
form = TaskForm()
return render(request, 'some_template.html', {'form': form})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
I have a website made on Django and the users able to leave a review and Ive tried to make it so they can add comments, however they add a comment it just saves it to the database rather then adding it to the post. If anyone knows how I could change my code so that it instead adds the comments to the review that they message on rather then them not appearing on the website at all.
views.py:
from django.shortcuts import render, redirect #Render is used to show the HTML, and redirect is used when the user needs to be sent to a different page automatically.
from .models import Review #This imports the Review database.
from .forms import ReviewForm, CommentForm #This imports the comments and review form.
from django.utils import timezone
from django.contrib.auth.decorators import login_required #This requires the user to be logged in.
def review(request):
return render(request, 'review/review.html')
#login_required(login_url='/accounts/login/')
def review_new(request):
if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.date = timezone.now()
post.author = request.user
post.save()
return redirect('/review')
else:
form=ReviewForm()
return render(request, 'review/post_edit.html', {'form': form})
def add_comment_to_post(request):
if request.method == "POST":
form = CommentForm(request.POST)
comment = form.save(commit=False)
comment.Review = review
comment.save() #This will save the comment to the database.
return redirect('reivew': review)
else:
form = CommentForm()
return render(request, 'review/add_comment_to_post.html', {'form': form})
models.py:
from django.db import models
from django.conf import settings
from django.utils import timezone
class Review(models.Model):
title = models.CharField(max_length=140)
body = models.TextField(max_length=3000)
date = models.DateTimeField()
author=models.ForeignKey(settings.AUTH_USER_MODEL, `on_delete=models.CASCADE, null=True)`
class comment(models.Model):
review = models.ForeignKey('review.Review', on_delete=models.CASCADE, related_name='comments', null=True)
author=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
text = models.TextField(max_length=3000)
created_date = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.text
urls.py:
from django.urls import path, include, re_path
from django.views.generic import ListView, DetailView
from review.models import Review
from . import views
urlpatterns = [
path('', ListView.as_view(
queryset=Review.objects.all().order_by("-date")[:25],
template_name="review/review.html")),
re_path('(?P<pk>(\d+))',DetailView.as_view(model=Review, template_name="review/post.html")),
path('new/', views.review_new, name='review_new'),
path('new/comment', views.add_comment_to_post, name='add_comment_to_post'),
]
I can see that you should change comment.Review = review to something like comment.review = Review.objects.get(id=review_id) where review_id is an id passed from the form. Also notice that your Comment model allows the review to be null, which means currently you are adding comments without linking them correctly to the original post/review they should be related to.
I have a contact form/model in Django that isn't showing up on the admin management page.
I have no idea why it isn't showing up, I have tried to debug by running migrations, and also renaming some of the model variables.
models.py
from django.db import models
class Contact(models.Model):
their_name = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
message = models.CharField(max_length=500)
def __str__(self):
return self.name
forms.py
from django import forms
class ContactForm(forms.Form):
their_name = forms.CharField(label='Name', max_length=100)
email = forms.EmailField(label='Email', max_length=100)
message = forms.CharField(label='Message', max_length=500, widget=forms.Textarea(attrs = {'id': 'Message_form'}))
admin.py
from django.contrib import admin
from .models import Contact
admin.register(Contact)
views.py
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from .models import Contact
from .forms import ContactForm
...
def contact(request):
valid_input = 'no input'
if request.method == 'POST':
valid_input = 'invalid input'
TheForm = ContactForm(request.POST)
if TheForm.is_valid():
valid_input = 'valid input'
name = TheForm['name']
email = TheForm['email']
message = TheForm['message']
Contact.objects.create(name=name, email=email, message=message)
else:
TheForm = ContactForm()
return render(request, 'BlogHome/pages/contact.html', {'TheForm': TheForm, 'valid_input': valid_input})
Could this be the way I am importing the model? I have no idea what is causing this problem.
In your admin.py create an admin class for your Contact model and after register this model in admin using that class.
class ContactAdmin(admin.ModelAdmin):
list_display = ('id', 'their_name', 'email', 'message')
admin.site.register(Contact, ContactAdmin)
I'm having an issue saving comments for a blog app I'm writing in Django. The error is: AttributeError at /blog/123456/ 'comment' object has no attribute 'is_valid'
My models.py:
from django.db import models
class comment(models.Model):
comID = models.CharField(max_length=10, primary_key=True)
postID = models.ForeignKey(post)
user = models.CharField(max_length=100)
comment = models.TextField()
pub_date = models.DateTimeField(auto_now=True)
views.py:
from django.http import HttpResponse
from django.shortcuts import render
from django.template import RequestContext, loader
from django.db.models import Count
from blog.models import post, comment
from site.helpers import helpers
def detail(request, post_id):
if request.method == 'POST':
form = comment(request.POST)
if form.is_valid():
com = form.save(commit=False)
com.postID = post_id
com.comID = helpers.id_generator()
com.user = request.user.username
com.save()
return HttpResponseRedirect('/blog/'+post_id+"/")
else:
blog_post = post.objects.get(postID__exact=post_id)
comments = comment.objects.filter(postID__exact=post_id)
form = comment()
context = RequestContext(request, {
'post': blog_post,
'comments': comments,
'form': form,
})
return render(request, 'blog/post.html', context)
I'm not sure what the issue is, from the tutorials/examples I've been looking at, form should have the attribute is_valid(). Could someone help me understand what I'm doing wrong?
comment is a Model. is_valid method are present in forms. I think what you wnat to do is create a ModelForm for comment like this:
from django import forms
from blog.models import comment
class CommentForm(forms.ModelForm):
class Meta:
model=comment
And use CommentForm as IO interface to comment class.
You can learn more about ModelForms at the docs
Hope this helps!