I need help with my code. I have read through the code several times and I didn't see anything wrong with it.
The user is expected to submit a job application and redirect the user to the dashboard, but it did not submit the job application neither does it direct the user to the dashboard.
here is my code:
mode.py
from django.db import models
from django.contrib.auth.models import User
class Job(models.Model):
title = models.CharField(max_length=255)
short_description = models.TextField()
long_description = models.TextField(blank=True, null=True)
created_by = models.ForeignKey(User, related_name='jobs', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
changed_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Application(models.Model):
job = models.ForeignKey(Job, related_name='applications', on_delete=models.CASCADE)
content = models.TextField()
experience = models.TextField()
created_by = models.ForeignKey(User, related_name='applications', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
Views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import AddJobForm, ApplicationForm
from .models import Job
def job_detail(request, job_id):
job = Job.objects.get(pk=job_id)
return render(request, 'jobs/job_detail.html', {'job': job})
#login_required
def add_job(request):
if request.method == 'POST':
form = AddJobForm(request.POST)
if form.is_valid():
job = form.save(commit=False)
job.created_by = request.user
job.save()
return redirect('dashboard')
else:
form = AddJobForm()
return render(request, 'jobs/add_job.html', {'form': form})
#login_required
def apply_for_job(request, job_id):
job = Job.objects.get(pk=job_id)
if request.method == 'POST':
form = ApplicationForm(request.POST)
if form.is_valid():
application = form.save(commit=False)
application.job = job
application.created_by = request.user
application.save()
#create_notification(request, job.created_by, 'application', extra_id=application.id)
return redirect('dashboard')
else:
form = ApplicationForm()
return render(request, 'jobs/apply_for_job.html', {'form': form, 'job': job})
forms.py
from django import forms
from .models import Job, Application
class AddJobForm(forms.ModelForm):
class Meta:
model = Job
fields = ['title','short_description','long_description']
class ApplicationForm(forms.ModelForm):
class Meta:
model = Application
fields = ['content', 'experience']
apply_for_job.html
{% extends 'core/base.html' %}
{% block content %}
Apply for job - {{ job.title }}
<form method="post" action=".">
{% csrf_token %}
{% if form.errors %}
{% for error in form.errors %}
<div class="notification is-danger">
{{ error }}
</div>
{% endfor %}
{% endif %}
<div class="field">
<label>Content</label>
<div class="control">
<textarea class="textarea" name="content" id="id_content"></textarea>
</div>
</div>
<div class="field">
<label>Experience</label>
<div class="control">
<textarea class="textarea" name="experience" id="id_experience"></textarea>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-success">Submit</button>
</div>
</div>
</form>
{% endblock %}
what could be wrong with my code?
the error in this line
<form method="post" action=".">
just delete the point, and it should work,
<form method="post" action="">
Related
I was getting that same error while click the like button, But the error was solved..
again after creating comment view and its other staff I'm getting that error again...When I click the comment button then the error appears..I'm very new to Django,,, help me please..
My project models.py, template page, urls.py, views.py are attached herewith
**models.py**
from email.policy import default
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Blog(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200, verbose_name="Put a Title")
blog_content = models.TextField(verbose_name="What is on your mind")
blog_image = models.ImageField(upload_to="blog_images", default = "/default.png")
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Comment(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_comment" )
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_comment")
comment = models.TextField()
comment_date = models.DateField(auto_now_add=True)
def __str__(self):
return self.comment
class Like(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_liked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_liked")
class Unlike(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name = "blog_unliked")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = "user_unliked")
**blog_page.html**
{% extends "main.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block content %}
<div style="text-align:center;">
<h2>{{blog.title}}</h2>
<img src="{{blog.blog_image.url}}" alt="" width="630px" height="300px">
</div>
<div style="text-align:center;">
{{blog.blog_content|linebreaks}}
</div>
{% if not liked and not unliked %}
<h4> Like </h4>
<h4>Unlike</h4>
{% elif unliked %}
<h4> Like </h4>
{% elif liked %}
<h4>Unlike</h4>
{% endif %}
<div>
<h4>
Comments:
</h4>
{% for comment in comments %}
<div>
{{ user }} <br>
<h5>{{ comment }}</h5>
</div>
{% endfor %}
<!-- <h6>Add your comment:</h6> -->
<form action="" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<a class="btn btn-sm btn-info" href="{% url 'comment' %}">Comment</a>
</form>
</div>
{% endblock content %}
**urls.py**
from django.urls import path
from blog_app import views
urlpatterns = [
path("", views.home, name='home'),
path("blog_page/<str:pk>/", views.blog_view, name='blog_page'),
path("like/<str:pk>/", views.like, name="like"),
path("unlike/<str:pk>/", views.unlike, name="unlike"),
path("comment/", views.comment, name="comment"),
]
**views.py**
from django.shortcuts import render
from . models import Blog, Comment, Like, Unlike
from . forms import CommentForm
# Create your views here.
def home(request):
blogs = Blog.objects.all()
context = {'blogs': blogs}
return render(request, 'blog_app/home.html', context)
def blog_view(request, pk):
blog = Blog.objects.get(id=pk)
form = CommentForm()
comments = Comment.objects.filter(blog=blog)
context = {"blog": blog, "comments": comments, "form":form}
return render(request, 'blog_app/blog_page.html', context)
def like(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
liked, like = Like.objects.get_or_create(blog=blog, user=user)
context = {"liked" : liked, "blog": blog }
return render(request, "blog_app/blog_page.html", context)
def unlike(request, pk):
blog = Blog.objects.get(id=pk)
user = request.user
unliked, unlike = Unlike.objects.get_or_create(blog=blog, user=user)
context = {"unliked" : unliked, 'blog': blog}
return render(request, "blog_app/blog_page.html", context)
def comment(request):
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
context = {}
return render(request, "blog_app/blog_page.html", context)
Your comment button is just a link, is it normal ? I think, you want to submit your form when you click on?
<div>
<h4>
Comments:
</h4>
{% for comment in comments %}
<div>
{{ user }} <br>
<h5>{{ comment }}</h5>
</div>
{% endfor %}
<!-- <h6>Add your comment:</h6> -->
<form action="{% url 'comment' %}" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<button type="submit" class="btn btn-sm btn-info">Comment</button>
</form>
</div>
And i think, your problem occured because you dispolay this template from comment view without set blog in context data.
def blog_view(request, pk):
blog = Blog.objects.get(id=pk)
form = CommentForm()
comments = Comment.objects.filter(blog=blog)
context = {"blog": blog, "comments": comments, "form":form}
return render(request, 'blog_app/blog_page.html', context)
def comment(request):
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect("blog_page", pk=form.instance.blog.pk)
return HttpResponse(status_code=400) # error case
else:
return HttpResponse(status_code=501) # try to GET page
Better solution is to pass blog pk in the url for being able to render page with error:
path("blog/<int:pk>/comment/", views.comment, name="comment")
<form action="{% url 'comment' blog.pk %}" method="POST">
{% csrf_token %}
{{form|crispy}} <br>
<button type="submit" class="btn btn-sm btn-info">Comment</button>
</form>
def comment(request, pk):
blog = get_object_or_404(Blog, pk=pk)
form = CommentForm()
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
form.save()
return redirect("blog_page", pk=blog.pk)
return render(request, "...", {"blog": blog, "form": form})
I'm trying to implement a feature where logged in users can comment on a blog post, but I'm a little stuck with the comments appearing on the page.
I can type in the comment and submit them. However, this is always returning a GET request. I tried adding method='post' to both the form and button tags, but this resulted in the following:
Method Not Allowed (POST): /post/1/
Method Not Allowed: /post/1/
I'm not really sure what the problem is. Any help would be much appreciated. Code snippets below.
post_detail.html with comment section:
<div class="content-section">
<legend class="border-bottom">Comments:</legend>
{% if user.is_authenticated %}
<form id="commentForm">
{% csrf_token %}
<fieldset class="form-group">
<div class="row">
<!-- <div class="col"></div> -->
<div class="col-1 text-right">
<img class="img-comment" src="{{ user.profile.image.url }}">
</div>
<div class="col-9">
<textarea type="text" id="commentIn" name="comment"
placeholder="Your comment..." required></textarea>
</div>
<div class="col"></div>
</div>
<div class="row">
<div class="col-10 text-right">
<button id="commentBtn" name="comment_button"
class="btn btn-outline-info" type="submit">Comment</button>
</div>
<div class="col"></div>
</div>
<hr>
</fieldset>
</form>
{% endif %}
<div id="commentDiv">
{% for cmnt in comments_list %}
<img class="img-comment"
src="{{cmnt.commentator.profile.image.url }}">
<a class="mr-2" >{{ cmnt.commentator }}</a>
<p class="article-content">{{ cmnt.comment }}</p>
<hr>
{% endfor %}
</div>
</div>
urls.py in blog app
urlpatterns = [
path('post/<int:pk>/', PostDetailView.as_view(), name="post-detail"),
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(User, related_name='like')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comment(models.Model):
commentator = models.ForeignKey(User, on_delete=models.CASCADE)
blog = models.ForeignKey(Post, on_delete=models.CASCADE)
comment = models.CharField(max_length=200)
date_added = models.DateTimeField(default=timezone.now)
class meta:
verbose_name_plural = 'comments'
def __str__(self):
return self.comment
views.py
class PostDetailView(DetailView):
model = Post
form = CommentForm()
def get_context_data(self, **kwargs):
if self.request.method == 'GET':
print('Render a blank form for users to fill out')
print(self.form)
elif self.request.method == 'POST':
print('Get the data from the POST request')
print(self.form)
status = 0
if self.request.user in self.object.likes.all():
status = 1
context = super().get_context_data(**kwargs)
context['comments_list'] = Comment.objects.filter(blog=self.object)
context['status'] = status
return context
and finally, the form itself:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['comment']
Don't mix class-based-view with method-based-view. You have to provide function that reads method and behave as it should. For get you usually will have built-in solutions, like form_class - in post() you can call it via form = self.get_form(). It generally looks like this:
class PostDetailView(DetailView):
model = Post
form_class = CommentForm
def post(self, request, *args, **kwargs):
form = self.get_form()
print('Get the data from the POST request')
print(form)
def get_context_data(self, **kwargs):
status = 0
if self.request.user in self.object.likes.all():
status = 1
context = super().get_context_data(**kwargs)
context['comments_list'] = Comment.objects.filter(blog=self.object)
context['status'] = status
return context
Another things to check ie. here: https://stackoverflow.com/a/45661979/12775662
I was able to save before without an issue using django.views.generic.CreateView. However, I can't save the same form using View.
Below are my codes:
models.py
class Project(models.Model):
name = models.CharField(max_length=200, verbose_name='Project Name')
user = models.ForeignKey(User,
on_delete=models.CASCADE,
blank=True,
null=True)
client = models.ForeignKey(Client,
on_delete=models.SET_NULL,
blank=True,
null=True)
deadline = models.DateTimeField(blank=True, null=True)
views.py
from django.views.generic import View
class ProjectCreateView(LoginRequiredMixin, View):
form_class = ProjectCreateForm
success_url = reverse_lazy('dashboard')
template_name = 'translation/project_form.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):
project_form = self.form_class(request.POST, instance=request.user)
if project_form.is_valid():
project_form.save()
return redirect(self.success_url)
else:
return render(request, self.template_name)
html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container mt-5 py-2 w-50 bg-dark text-white">
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success mt-3">Confirm</button>
</form>
</div>
{% endblock content %}
urls.py
path('project/new', views.ProjectCreateView.as_view(), name='project-add'),
When I submit the form in html, it doesn't render any error message. It simply redirects to the self.success_url and the intended object is not saved.
Any help or advice will be much appreciated. Thank you!
Edit:
Forgot to include the codes for the Form:
forms.py
class ProjectCreateForm(forms.ModelForm):
class Meta:
model = Project
widgets = {
'deadline' : forms.DateInput(attrs={'type':'date'})
}
fields = ['name', 'client', 'deadline']
IntegrityError at /add-media/
UNIQUE constraint failed: users_media.user_idUNIQUE constraint failed: users_media.user_id
UNIQUE constraint failed: users_media.user_id
I am trying to get data from a specific user, but instead I am getting all data from all users in data base.
views.py
#login_required
def profile(request):
if request.method == 'GET':
media_images = Media.objects.all()
context = {
'media_images':media_images,
}
return render(request, 'users/profile.html', context)
#login_required
def add_media(request):
if request.method == 'POST':
form = MediaForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user= request.user
form.save()
return redirect('http://127.0.0.1:8000/')
else:
form = MediaForm()
return render(request, 'users/add_media.html', {'form':form})
models.py
class Media(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
image_name = models.CharField(max_length=50)
image_description = models.CharField(max_length=80)
image_image = models.ImageField(upload_to='media', default='default.jpg')
def __str__(self):
return f'{self.user.username} Media'
template
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section container">
<div class="row justify-content-md-between ml-4 align-items-center ">
<div class='col-md-'>
<img width='100' src="{{user.profile.image.url}}" alt=""><span class='ml-4'>{{ user.username }}</span>
</div>
<div class='mr-4'>
<a class='mr-4' href="{% url 'add-media'%}">Add media</a>
Settings
</div>
</div>
</div>
<div class="content-section">
<h2 class='center'>Your Medias</h2>
{% for media in media_images %}
<div class="profile-content-and-manage">
<div class="profile-content-div">
<p class='profile-paragraph-image paragraph-image-name'>{{media.image_name}}</p>
<p class='profile-paragraph-image paragraph-image-description'>{{media.image_description}} </p>
<img height="97px" class='profile-image' src='{{media.image_image.url}}'>
</div>
<div class="profile-manage-div">
<p class="profile-paragraph-image profile-paragraph-image-delete">X</p> <span class="profile-paragraph-image">Edit</span>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
forms.py
class MediaForm(forms.ModelForm):
class Meta:
model = Media
fields = ['image_name', 'image_description', 'image_image']
signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
You filter the files, such that the user refers to the request.user:
#login_required
def profile(request):
media_images = Media.objects.filter(user=request.user)
context = {
'media_images':media_images,
}
return render(request, 'users/profile.html', context)
I'm trying to upload a user photo and show it in homepage.
problem 1 : When i upload an image from admin section it gets saved in database but it doesn't show up in 'homepage.html'.
Problem 2 : When i try to upload an image using 'profile.html' template the image is not even saved in database.
I've tried several solution from stackoverflow but failed to solve my problem. My code is given below:
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
first_name= models.CharField(max_length=100, default='', blank=True)
last_name = models.CharField(max_length=100, default='', blank=True)
email = models.CharField(max_length=100, default='', blank=True)
pro_pic = models.ImageField(upload_to='profilepic',blank=True)
phone = models.CharField(max_length=20, blank=True, default='')
city = models.CharField(max_length=100, default='', blank=True)
country = models.CharField(max_length=100, default='', blank=True)
job = models.CharField(max_length=20, blank=True, default='')
organization = models.CharField(max_length=100, default='', blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
forms.py
from django.contrib.auth.models import User
from django import forms
from .models import UserProfile
class UserForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['first_name', 'last_name', 'email']
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['pro_pic','phone', 'city', 'country', 'job', 'organization']
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'obs/media')
views.py
#login_required
#transaction.atomic
def update_profile(request):
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
profile_form = ProfileForm(request.POST, instance=request.user.profile)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request,'Your profile was successfully updated!')
return redirect('obs:homepage')
else:
messages.error(request, 'Please correct the error below.')
else:
user_form = UserForm(instance=request.user)
profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'obs/profile.html', {
'user_form': user_form,
'profile_form': profile_form
})
profile.html
{% extends 'obs/base.html' %}
{% block body %}
{% load staticfiles %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href='https://fonts.googleapis.com/css?family=Satisfy' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="{% static 'obs/profilecss.css' %}"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<head>
<title>Profile</title>
</head>
<div class="container">
<div class="row">
<div class="col-md-5 col-md-offset-3">
<div class="panel panel-default">
<div class="panel-heading">
<span class="glyzphicon glyphicon-user"></span> Update User Profile</div>
<div class="panel-body">
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form method="post" class="hello">
{% csrf_token %}
{% for field in user_form %}
<div class="form-group">
<label class="col-sm-15 control-label">
{{ field.label_tag }}</label>
{{ field }}
</div>
{% endfor %}
{% for field in profile_form %}
<div class="form-group">
<label class="col-sm-15 control-label">
{{ field.label_tag }}</label>
{{ field }}
</div>
{% endfor %}
<center>
<div class="buttonHolder">
<button class="button tick" type="submit"></button>
</div>
</center>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
homepage.html
<div class="profile-userpic">
<img src="{{ profile_form.pro_pic.url }}" class="img-responsive" alt="">
</div>
urls.py (project)
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^onlinebookshare/', include('registration.urls', namespace="accounts")),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
view for homepage:
#login_required
#transaction.atomic
def update_home(request):
user_form = UserForm(instance=request.user)
profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'obs/homepage.html', {
'user_form': user_form,
'profile_form': profile_form
})
First you need to create the MEDIA_ROOT directory and upload_to directory as you specified.
MEDIA_ROOT=os.path.join(BASE_DIR,'obs/media')
pro_pic = models.ImageField(upload_to='profilepic',blank=True)
In the form tag where you upload the profile pic you need to add the following enctype='multipart/form-data' like
<form method="post" enctype="multipart/form-data" class="hello">.
In the update_profile view change the following line:
profile_form = ProfileForm(request.POST, instance=request.user.profile)
to
profile_form = ProfileForm(request.POST, instance=request.user.profile, request.FILES or None)
Hope this will help.
What you're doing is a bit odd. You're trying to access the already-uploaded file, whose URL is stored in a field of the model, via the form. The immediate cause of the problem is that a form field doesn't know about URLs, it just has a value. You would need to access it via the underlying form instance, which you passed in as the profile - so, {{ profile_form.instance.pro_pic.url }}.
But I can't see why you are doing this. Displaying things is not the responsibility of the form anyway. You should just use the profile directly, which is already available via the user object.
{{ user.profile.pro_pic.url }}
For the second problem, you need to pass the uploaded files to the form:
profile_form = ProfileForm(request.POST, request.FILES, instance=request.user.profile)