This view is supposed to find a blog post and change it's information, but instead of that it just makes a new Blog object with the new (and old) information.
The update view
#login_required
def view_updatepost(request, blog_id):
if not request.user.is_staff or not request.user.is_superuser:
raise Http404
#post = Blog.objects.get(pk=blog_id)
post_to_be_changed = get_object_or_404(Blog, pk=blog_id)
form = BlogForm(request.POST or None, instance=post_to_be_changed)
if form.is_valid():
post_to_be_changed = form.save(commit=False)
#
#
post_to_be_changed.save()
#messages.success(request, "<a href='#'>Item</a> Saved", extra_tags='html_safe')
return HttpResponseRedirect(post_to_be_changed.get_absolute_url())
context = {
'post_to_be_changed': post_to_be_changed,
'form': form,
}
return render(request, 'blog/makepost.html', context)
The template used by the view makepost.html
{% extends "base.html" %}
{% load staticfiles %}
{% block main_content %}
<!-- Page Header -->
<!-- Set your background image for this header on the line below. -->
<header class="intro-header" style="background-image: url('{% static "img/about-bg.jpg" %}')">
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="page-heading">
<h1>Make a Post</h1>
<hr class="small">
<span class="subheading">Share with the World.</span>
</div>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
{% if not user.is_authenticated %}
You must be <u>logged in</u> to make a post.
{% else %}
<form action="{% url "makepost" %}" method="post">
{% csrf_token %}
{{form.as_p}}
<div align="center">
<input class="btn btn-default" type="submit" value="Post to Blog" onclick="window.location='{% url "" %}';"/>
{# Home #}
</div>
</form>
{% endif %}
</div>
</div>
</div>
<hr>
{% endblock main_content %}
The models.py
from django.db import models
import datetime
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length=250)
subtitle = models.CharField(max_length=250, null = True, blank=True)
date_added = models.DateTimeField(default=datetime.datetime.now())
image = models.TextField(max_length=1000, null = True, blank=True)
tags = models.TextField(max_length=500, null=True, blank=True)
article = models.TextField(max_length=15000, null=True, blank=True)
author = models.CharField(max_length=150, null=True, blank=True)
def get_absolute_url(self):
return "/blog/%i" % self.pk
The forms.py
from django import forms
from .models import Blog
import datetime
class PostForm(forms.Form):
title = forms.CharField()
subtitle = forms.CharField(required=False)
date_added = forms.DateTimeField()
image = forms.URLField(required=False)
tags = forms.CharField(required=False)
article = forms.CharField()
author = forms.CharField()
class BlogForm(forms.ModelForm):
class Meta:
model = Blog
fields = ('title', 'subtitle',
'image', 'tags', 'article')
It seems that you are not referring to your update view in your form action url:
<form action="{% url **"makepost"** %}" method="post">
Related
I have a model with a text field:
models.py
class Techtip(models.Model):
title = models.CharField(max_length=150)
year = models.PositiveIntegerField()
year2 = models.PositiveIntegerField()
make = models.CharField(max_length=30)
model = models.CharField(max_length=30)
description = models.TextField(max_length=10000)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
date_created = models.DateTimeField(auto_now_add=True)
date_revised = models.DateTimeField(null=True)
additional_field = models.TextField(max_length=5000, null=True, blank=True)
additional_field2 = models.TextField(max_length=5000, null=True, blank=True)
image1 = models.ImageField(upload_to=user_directory_path, null=True, blank=True)
image2 = models.ImageField(upload_to=user_directory_path, null=True, blank=True)
image3 = models.ImageField(upload_to=user_directory_path, null=True, blank=True)
def __str__(self):
return self.title
If a create a Techtip and give it a description of:
"Hello, This is line one of the disctription.
This is line two.
and this is line 3."
When using {{techtip.deescription}} in the template I receive this:
"Hello, This is line one of the disctription.
This is line two.
and this is line 3."
However, if you bring up a form to edit the description, the spaces are there. It is also displayed correctly in the admin panel.
Here is the form:
forms.py
class TechtipFormModel(forms.ModelForm):
"""This form creates and edits techtips."""
class Meta:
model = Techtip
fields = '__all__'
exclude = ('user', 'date_revised', 'additional_field', 'additional_field2', 'image1', 'image2', 'image3')
def __init__(self, *args, **kwargs):
super(TechtipFormModel, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'id-TechtipForm'
self.helper.form_method = 'post'
self.helper.add_input(Submit('submit', 'Submit'))
self.fields['description'].strip = False
Here are the views for editing a Techtip or displaying one. The spacing works correctly when using the edit form but not while displaying a Techtip.
views.py
#login_required
def techtip_detail(request, pk):
# display techtip details. In template: if user is the creator of Techtip they can update/delete
tech_id = pk
user = request.user
techtip = Techtip.objects.get(pk=tech_id)
context = {'techtip': techtip}
return render(request, 'techtips/view_techtip.html', context)
class TechtipEdit(LoginRequiredMixin,
UpdateView,):
model = Techtip
form_class = TechtipFormModel
template_name = 'techtips/edit_techtip.html'
def get_success_url(self):
return reverse('manage_techtips')
def dispatch(self, request, *args, **kwargs):
# check for user logged in
# check for user permission:
# Take pk from kwargs
pk = kwargs.get('pk') # example
# Take user from request
user = request.user
# check permission
try:
Techtip.objects.get(pk=pk, user=user)
return super(TechtipEdit, self).dispatch(request, *args, **kwargs)
except Techtip.DoesNotExist:
return HttpResponse(status=403)
and here are the templates!
view_techtip.html
{% extends "techtips/base.html" %}
{% block body %}
<div class="row">
<div class="col-md-12">
<div class="container-fluid" align="left">
<div id="punchlist">
<h3 style="margin-bottom: 0px;">Title:</h3>{{ techtip.title }}<br>
<h3 style="margin-bottom: 0px; margin-top: 20px;">Make:</h3> {{ techtip.make }}<br>
<h3 style="margin-bottom: 0px; margin-top: 20px;">Model:</h3> {{ techtip.model }}<br>
<h3 style="margin-bottom: 0px; margin-top: 20px;">Beginning Year:</h3> {{ techtip.year }}<br>
<h3 style="margin-bottom: 0px; margin-top: 20px;">Ending Year:</h3> {{ techtip.year2 }}<br>
<h3 style="margin-bottom: 0px; margin-top: 20px;">Description:</h3> {{ techtip.description }}<br>
</div>
</div>
</div>
</div>
{% if techtip.user.id == user.pk or request.user.is_superuser == TRUE %}
<br>
<form method="GET" action="{% url 'edit_techtip' techtip.pk %}">
<span class="techtip-button-1">
<button type="submit" value="EDIT">Edit</button>
</span>
</form>
{% endif %}
{% if request.user.is_superuser == TRUE %}
<form method="POST" action="{% url 'delete_techtip' techtip.pk %}">
{% csrf_token %}
<span class="techtip-button-1">
<button type="submit" value="DELETE">Delete</button>
</span>
</form>
{% endif %}
<br><br>
<br>
{% if techtip.user.id != user.pk %}
Author: {{techtip.user}}
{% endif %}
{% if techtip.user.id == user.pk %}
Author: You
{% endif %}
{% endblock %}
and
edit_techtip.html
{% extends 'techtips/base.html' %}
{% block body %}
{% load crispy_forms_tags %}
{% crispy form form.helper %}
{% endblock %}
Thanks in advance!
I did some research and added
self.fields['description'].strip = False
to the form class but then later realized that wouldn't help because this form class has no part of passing an object into the template and using Django template language.
I'm trying to add a delete button for a single comment of current user inside a post. I tried the function below in my views.py , but it comes back as error: Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/comments/15/delete/
Raised by: feed.views.comment_delete
Any ideas what I'm doing wrong ?
views.py
#login_required
def comment_delete(request, pk):
comment = get_object_or_404(Comments, pk=pk)
if request.user.id == comment.username_id:
Comments.objects.get(pk=pk).delete()
messages.error(request, f'Comment Deleted')
return redirect('post-detail', pk=pk)
models.py
class Post(models.Model):
description = models.TextField(max_length=255)
pic = models.ImageField(upload_to='path/to/img', blank=True)
date_posted = models.DateTimeField(default=timezone.now)
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.description
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Comments(models.Model):
post = models.ForeignKey(Post, related_name='details', on_delete=models.CASCADE)
username = models.ForeignKey(User, related_name='details', on_delete=models.CASCADE)
comment = models.CharField(max_length=255)
comment_date = models.DateTimeField(default=timezone.now)
post_detail.html
<h4 class="comment_text">Comments</h4>
<div class="row">
<div class="col-xl-9 col-md-10 m-auto order-xl-2 mb-0 mb-xl-0">
{% if post.details.all %}
<div class="card card-signin my-0">
{% for detail in post.details.all %}
<div class="card-body">
<a href="{{ detail.username.profile.get_absolute_url }}">
<img src="{{ detail.username.profile.image.url }}" class="rounded-circle" width="30" height="30" alt="">
</a>
<a class="text-dark" href="{{ detail.username.profile.get_absolute_url }}"><b>{{ detail.username }}</b></a>
<a class="comment_delete" href="{% url "comment-delete" user.id %}">delete</a>
<br><small>{{ detail.comment_date }}</small><br><br>
<p class="card-text text-dark">{{ detail.comment }}</p>
</div>
<hr class="my-1">
{% endfor %}
</div>
{% else %}
<p>No comments to show!</p>
{% endif %}
</div>
In your template you write {% url "comment-delete" user.id %} when in fact the argument that the view expects is the comments id/pk. Change it to {% url "comment-delete" detail.pk %}
I am really lost and trying to solve this issue for hours. I am working on this social media for photographers, where they can comment each other's photos. I set up forms for comments, but I am getting AttributeError :
'Post' object has no attribute 'get_content_type'
This is my Views.py - photo_detail, where is the error :
def photo_detail(request, id):
instance = get_object_or_404(Post, id=id)
comments = Socialmedia.objects.filter_by_instance(instance)
initial_data = {
"content_type": instance.get_content_type,
"object_id": instance.id
}
socialmedia_form = SocialmediaForm(
request.POST or None, initial=initial_data)
if socialmedia_form.is_valid():
print(socialmedia_form.cleaned_data)
context = {
"title": instance.title,
"photo": instance.photo,
"instance": instance,
"comments": comments,
"socialmedia_form": socialmedia_form,
}
return render(request, "photo_detail.html", context)
When I comment out line "content_type": instance.get_content_type,, the error disaapers, but after writing comment its saying field is required and not posting anything , so it doesnt load the data from comment.
And here is my models.py :
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
from socialmedia.models import Socialmedia, SocialmediaManager
from django.contrib.contenttypes.models import ContentType
def upload_location(instance, filename):
return '%s/%s' % (instance.id, filename)
class Post(models.Model):
# category = models.ForeignKey(Type, blank=True, null=True, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
title = models.CharField(max_length=200)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
time = models.DateTimeField(auto_now=False, auto_now_add=True)
photo = models.ImageField(upload_to=upload_location,
null=True, blank=True,
height_field="height_field",
width_field="width_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("photo_detail", kwargs={"id": self.id})
#property
def get_content_type(self):
instance = self
content_type = ContentType.objects.get_for_model(instance.__class__)
return content_type
And the last page photo_detail.html, where I am trying to implement it.
{% extends "base.html" %}
{% block content%}
<div class="col-sm-8 col-sm-offset-6">
{% if instance.photo %}
<img src="{{ instance.photo.url }}" class="img-responsive"/>
{% endif %}
<h1>{{ title }} </h1>
<p>Author: {{ instance.user}}</p>
<p><div class="fb-like" data-href="https://developers.facebook.com/docs/plugins/" data-width="" data-layout="button" data-action="like" data-size="small" data-share="true"></div></p>
<br>
<p>Updated : {{ instance.updated }}<br/></p>
<p> Created :{{ instance.time }}<br/></p>
<div>
{{instance.comments.all}}
<p class="lead">Comments</p>
<form method="POST" action="."> {% csrf_token %}
{{ socialmedia_form}}
<input type="submit" value="Post" class="btn btn-default">
</form>
{% for comment in comments %}
<div class="">
{{ comment.content }}
{{comment.user}} {{comment.time | timesince }} ago
</div>
{% endfor %}
</div>
</div>
{% endblock %}
I want to know how to upload and display the image.
I do have the classes in views.py.
class ArticleUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Article
fields = ('title', 'body', 'image', 'source_url')
template_name = 'article_edit.html'
def test_func(self):
obj = self.get_object()
return obj.author == self.request.user
class ArticleCreateView(LoginRequiredMixin, CreateView):
model = Article
template_name = 'article_new.html'
fields = ('title', 'body', 'image', 'source_url')
login_url = 'login'
def test_func(self):
obj = self.get_object()
return obj.author == self.request.user
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
And the relevant classes in the models.py are like as follow.
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(
upload_to='media/', null=True, blank=True)
source_url = models.URLField(blank=True, null=True, max_length=300)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
class Comment(models.Model):
article = models.ForeignKey(Article,
on_delete=models.CASCADE, related_name='comments', )
comment = models.CharField(max_length=140)
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE),
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse('article_list')
The article_list.html file is:
{% extends 'base.html' %}
{% load static %}
{% block title %}Articles{% endblock title %}
{% block content %}
{% for article in object_list %}
<div class="card">
<div class="card-header">
<span class="font-weight-bold">{{ article.title }}</span> ·
<span class="text-muted">by {{ article.author }} |
{{ article.date }}</span>
</div>
<div class="card-body">
{{ article.body|linebreaks}}
{% comment %} {% if article.image.url|length > 0 %}
<img src="{{ article.image.url }}" width="200px">
{% else %}
<img src="{% static '/media/mrDoctor.jpg' %}" width="200px" />
{% endif %} {% endcomment %}
<img src="{% static 'articles/mrDoctor.jpg' %}" alt="Image" width="200px" />
Link
Edit
Delete
</div>
<div class="card-footer">
{% for comment in article.comments.all %}
<p>
<span class="font-weight-bold">
{{ comment.author }} ·
</span>
{{ comment }}
</p>
{% endfor %}
</div>
</div>
<br />
{% endfor %}
{% endblock content %}
The user can select the image file from the form.
I can not display the image selected from the input form shown above on the screen shot. I want to display the images dynamically, i.e., when the user choose the image file from the input form. I know I should change the part:{% static '/media/mrDoctor.jpg' %}. When I tried the commented part of article_list.html, i.e., {% if article.image.url|length > 0 %}, it did not work. I will appreciate it if you help me to fix the problem. Many thanks.
After reflecting #Hybrid suggestions, I was able to show the image on the first article but the second and the third one show only the file names.
You can do this by using JavaScript to detect when a user selects an image, and then replacing an <img /> tags src dynamically.
Example code:
<img id="image" />
<input id="files" type="file" />
<script>
document.getElementById("files").onchange = function () {
var reader = new FileReader();
reader.onload = function (e) {
// get loaded data and render thumbnail.
document.getElementById("image").src = e.target.result;
};
// read the image file as a data URL.
reader.readAsDataURL(this.files[0]);
};
</script>
I am beginner in django . I would like to make an application that allows a user to record examinations and related images.
So i try to uploading multiple images in Django for a single post according this topic http://qasimalbaqali.com/uploading-multiple-images-in-django-for-a-single-post/.
But nothing happens when I press the button
I explain my models. A document is a generic class. An exam is a document, a document contains files.
class Document(models.Model):
class Meta:
db_table = 'Document'
slug = models.SlugField(max_length=100)
user = models.ForeignKey(User)
level = models.ForeignKey(ClassLevel, null=False, default=1)
school = models.ForeignKey(School, null=False, default=1)
nb_views = models.IntegerField(default=0)
name = models.CharField(max_length=100)
matter = models.ForeignKey(ClassTopic, null=False, default=1)
status = models.IntegerField(choices=DOCUMENT_STATUS, default=1)
creation_date = models.DateTimeField(auto_now_add=True)
deletion_date = models.DateTimeField(auto_now_add=False, default=None, null=True)
def __unicode__(self):
return self.name + " (" + str(self.status) + ") " + self.school.name
class DocumentFile(models.Model):
class Meta:
db_table = 'DocumentFile'
file = models.FileField(upload_to="photo/", null=True)
document = models.ForeignKey(Document)
def __unicode__(self):
return self.file
class Exam(Document):
class Meta:
db_table = 'Exam'
year_exam = models.IntegerField(choices=EXAM_YEAR_CHOICES, default=1)
mock_exam = models.IntegerField(choices=EXAM_TYPE, default=1)
def __unicode__(self):
return self.name + " " + self.matter
I create two forms. For exam and for file.
class UploadFileForm(ModelForm):
#description = forms.CharField(max_length=30)
file = forms.FileInput()
helper = FormHelper()
helper.form_id = 'file-input'
helper.form_show_labels = False
helper.layout = Layout(PrependedText('file', "", placeholder=""))
#helper.layout.insert(1, HTML("<input type='file' class='file' multiple data-show-upload='false' data-show-caption='true'>"))
class Meta:
model = DocumentFile
fields = ('file',)
#exclude = ("file_type", "file_path", "document")
class CreateExamForm(forms.ModelForm):
helper = FormHelper()
helper.form_id = 'CreateExam'
helper.form_show_labels = False
helper.layout = Layout(
PrependedText("matter", "", ""),
PrependedText("level", "<small class='text-warning'>Selectionner la classe. </small>", ""),
PrependedText("school", "<pre><small>Selectionner l\'établissement. </small></pre>", css_class="selectpicker"),
PrependedText("year_exam", ""),
PrependedText("mock_exam", ""))
class Meta:
model = Exam
exclude = ("slug", "user", "nb_views", "name", "status", "creation_date", "deletion_date")
My view
def createexam(request):
# Creation du formulaire + upload des images
doc_form = CreateExamForm(auto_id=True)
# Création du formset avec n itération : extra=2
file_form_set = modelformset_factory(DocumentFile, form=UploadFileForm, extra=1)
# Récupération du formulaire géré par le mécanisme formset
#formset = sortedfilesform()
if request.method == "POST":
doc_form = CreateExamForm(request.POST)
files_form = file_form_set(request.POST, request.FILES, queryset=DocumentFile.objects.none())
if doc_form.is_valid() and files_form.is_valid():
doc_save = doc_form.save(commit=False)
doc_save.user = request.user
for fileform in files_form.cleaned_data:
image = fileform['file']
one_image = DocumentFile(document=doc_save, file_value=image)
one_image.save(commit=False)
transaction.commit()
msg = FORM_PROPERTIES.FORM_EXAM_STORED.replace("user", request.user.nickname)
messages.add_message(request, messages.SUCCESS, msg)
form = LoginForm()
context = {'form': form}
return render_to_response(template_name='login.html', context=context, context_instance=RequestContext(request))
else:
messages.add_message(request, messages.SUCCESS, FORM_PROPERTIES.FORM_EXAM_ERROR)
context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
return render(request, 'createexam.html', context)
else:
context = {'doc_form': doc_form, 'file_form_set': file_form_set, }
return render(request, 'createexam.html', context)
my url.py
urlpatterns = [
# Examples:
url(r'^$', home, name='home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^$', home),
url(r'^home', home),
url(r'^login', login),
url(r'^logout', logout),
url(r'^register$', register),
url(r'^createexam$', createexam),
url(r'^account/reset_password', reset_password, name="reset_password"),
]
My template is simple
<div id="login-overlay" class="modal-dialog">
<div class="row">
<div class="panel panel-info" >
<div class="panel-heading">
<div class="panel-title">Créer un examen</div>
</div>
<div class="panel-body" >
<div class="col-sm-12">
<form id="post_form" method="POST" action='.'
enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in doc_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in doc_form %}
{{ field }} <br />
{% endfor %}
{{ file_form_set.management_form }}
{% for form in file_form_set %}
{% crispy form %}
{% endfor %}
<input type="submit" value="Add recipe" class="submit" />
</form>
</div>
</div>
</div>
</div>
Everything seems good form me. But my submit does no think.
I 'm on it for two days.
I read and tried many things. Does anybody can help me please (Sorry for my english)
There are a couple of things wrong here.
Firstly you are not showing the form errors in the template, so the user has no way of knowing why their submission is invalid. Make sure you either do {{ field.errors }} after every field, or do {{ form.errors }} for the whole form at once; and remember to do this both form the main form and the image formset.
Secondly, you're saving the forms with commit=False, so they are not persisted to the database. It's fine to do that if you want to add extra data not included in the form, but you then need to remember to actually persist the object by calling eg doc_save.save().
I solved my problem when i put my main form body in <table> ... </table>
<form id="CreateExamForm" method="POST" enctypr="multipart/form-data">
{% csrf_token %}
<table>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Classe - Matière - Date</h3>
<span class="pull-right"><i class="glyphicon glyphicon-chevron-up"></i></span>
</div>
<div class="panel-body">
{% crispy doc_form %}
{{ file_form_set.management_form }}
{% for f_form in file_form_set %}
<div class="form-inline">
{% crispy f_form %}
</div>
{% endfor %}
</div>
</div>
</table>
<input type="submit" value="Add recipe" class="submit" />
</form>