Display users' images in Django - django

I am learning Django and currently trying to make a simple website where users can post topics and stuff. What I want is only the uploaded images that belong to a certain topic to display when you open the topic. But I am so stuck at it now I can't get any image come up on the pages. I've tried many different things but none's worked so far. I can't get my head around how exactly the template should look like and how do I link it to the topic page...and my view is probably far from right but I've tried a lot of things and it's all got a bit messy...pretty much it's been 2 days of hassle and I will appreciate any directions
Thank you in advance
This is what i have:
models.py
class Image(models.Model):
"""images representation"""
image=models.ForeignKey(Topic, on_delete=models.CASCADE)
image=models.ImageField(upload_to= 'media/')
caption=models.CharField(max_length= 100)
uploaded_at=models.DateTimeField(auto_now_add=True)
views.py
def upload_image(request, topic_id):
"""Upload images"""
topic=Topic.objects.get(id=topic_id)
if request.method != 'POST':
# No data submitted; creaete a blank form
form=ImageForm()
else:
# Data submitted; Process data
form=ImageForm(request.POST, request.FILES)
if form.is_valid():
instance=form.save(commit=FALSE)
instance.topic=topic
instance.save()
return HttpResponseRedirect(reverse('the_horror:topic',
args=[topic_id]))
images=Image.objects.all()
context={'form':form, 'topic':topic, 'images':images}
return render(request, 'the_horror/topic.html', context)
upload_image.html
{% extends 'the_horror/base.html' %}
{% block content %}
{% if images %}
<ul>
{% for image in images %}
<li>
<a href="{{image.image.url}}">
<img source="{{image.image.url}}" alt="sth"></a>
</li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<form action="{% url 'upload_image' %}" method= "post" enctype= "multipart/form-data">
{% csrf_token %}
<input type="file" name="image"/>
<input type="submit" name="submit" value="Upload"/>
<button type="submit">name="upload photo"</button>
</form>
As i said i am not sure how to pass the images to the topic template
topic.html
{% extends 'the_horror/base.html' %}
{% block content %}
<p>Topic:{{topic}}</p>
<p>
edit topic
</p>
<p>Entries</p>
<p>
Add a new entry
</p>
<ul>
{% for entry in entries %}
<li>
<p>{{entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{entry.text|linebreaks}}</p>
<p>
<image class= "Image" source={{>
</p>
<p>
edit entry
</p>
</li>
{% empty %}
<li>
There are no entries for this topic yet.
</li>
{% endfor %}
</ul>
{% endblock content %}
urls.py
path('upload_image/<topic_id>', views.upload_image, name= 'upload_image'),
# Single topic page

On your models.py you don't need to write media on your upload_to option, what you have to do is to add to your urls.py static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) here
urls.py
urlpatterns = [
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
On your upload_image.html why are you creating 2 input. Personally I use an input to take the image file
upload_image.html
...
<input name="image" type="file">
...
then in the views you started well but I will do as follow to store the image
views.py
def upload_image(request, topic_id):
...
imageObject = Image.objects.create()
image = request.FILES['image']
imageObject.image = image
...
Finally, you will get your image this way
topic.html
<img src="{{MEDIA_URL}}{{imageObject.image}}" alt="image">
Usually it works, I made several projects with this method or similar methods, if you still got error or question let me know

Related

How to delete a record through a button in django

I have created a model Announcement in models.py file
class Announcement(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
def __str__(self):
return self.title
And for deleting a record of Announcement I have created the following view
def AnnouncementDelete(request, pk):
announcement = get_object_or_404(Announcement, pk=pk)
if request.method=='POST':
announcement.delete()
return redirect('/')
return render(request, 'classroom/announcement_confirm_delete.html', {'announcement': announcement})
The delete view of announcement (that is AnnouncementDelete) has the following url
path("delete/<int:pk>/", view=views.AnnouncementDelete, name="AnnouncementDelete"),
If i enter
http://127.0.0.1:8000/classroom/delete/3
on browser it is deleting the Announcement having pk = 3
Now I want a button to directly delete my record without the need of typing http://127.0.0.1:8000/classroom/delete/3 on browser
I have tried the following methods in my allannouncement.html file
{% extends "classroom/base.html" %}
{% block content %}
<h1>Announcements</h1>
{% for announcement in announcements %}
<!-- starting loop (posts is keyword from view) -->
<div style="border-style: solid;">
{% if announcement.teacher.user == request.user %}
<div>
Delete
</div>
{% endif %}
{{ announcement.pk }}
<a class="mr-2">Posted by: {{ announcement.teacher }}</a>
<h2><a class="article-title">{{ announcement.title }}</a></h2>
<p class="article-content">{{ announcement.content}}</p>
</div>
{% endfor %}
{% endblock content %}
but it is giving the following error
NoReverseMatch at /classroom/allannouncement/
Reverse for 'AnnouncementDelete' with no arguments not found. 1 pattern(s) tried: ['classroom/delete/(?P<pk>[0-9]+)/$']
then I also tried passing pk with url like
Delete
But it is giving the following error
TemplateSyntaxError at /classroom/allannouncement/
Could not parse the remainder: ',' from ','
Remove common #refer this
Delete
instead of a link add a form.
Add
{% load crispy_forms_tags %}
in your html file and then add
{% if announcement.teacher.user == request.user %}
<div>
<form action="{% url 'classroom:AnnouncementDelete' announcement.id %}"
method="post">
{% csrf_token %}
<input type="submit" value="Delete">
</form>
</div>
{% endif %}

TemplateDoesNotExist at /inventory/render_results/ error message in django

I am using code that I've used before but it is throwing an error, 'TemplateDoesNotExist at /inventory/render_results/' and I cannot find the typo or logic miss. The template does exist and when I review the code, the query is performing correctly. I'm at a loss.
search_device_list.html
{% extends "inventory/base.html" %}
{% block content %}
<h2 align="left">Search Page</h2>
<form action="{% url 'render_results' %}" method="POST" >
{% csrf_token %}
<body>
<table>
<tr>
<td><b>Locations: </b></td>
<td>
<select name="location_name">
{% for locations in locations %}
<option value="{{locations.location_name}}">{{locations.location_name}}</option>{% endfor%}
</select>
</td>
<td><input type="submit" value="Submit"/></td>
</tr>
</table>
{% endblock content %}
render_results.html
<html>
<h2 align="left">Render Device List based on Location Choice</h2>
<b> Locations: </b><br>{{locations }} <br><br><br>
<b> Devices: </b><br>
{% for device in devices %}{{device.device_name}} <br>{% endfor %} </td>
<br>
<button type="submit" id="save">Save</button>
</html>
views.py
def render_results (request):
location_name = request.POST.get('location_name')
my_devices = Devices.objects.filter(locations = Locations.objects.get(location_name = location_name))
context = {"devices": my_devices,
"locations": location_name}
return render(request, 'inventory/render_results.html', context)
def search_device_list(request):
locations = Locations.objects.all()
print(locations)
context = {"locations": locations}
for locations in context['locations']:
print(locations)
location_name=request.POST.get('location_name')
if request.method == 'GET':
form = LocationsForm()
print(locations)
return render(request, 'inventory/search_device_list.html', context)
and finally urls.py
...
url(r'^search_device_list/$', views.search_device_list, name='search_device_list'),
url(r'^render_results/$', views.render_results, name='render_results'),
Do you have os.path.join(BASE_DIR, 'templates') set in your settings file?
This would be in the templates section. This code should replace the empty list for DIRS = []
https://docs.djangoproject.com/en/3.0/topics/templates/
This is just speculation of course. It would help to see the full settings.py and urls.py. Also as previous stated, make sure the path to your templates is app_name/templates/app_name/html_file
<form action="{% url 'inventory:render_results' %}" method="POST" >
If your getting NoReverseMatch Error simply means you have an issue with the URL pattern either on the HTML end or in the URLconf. The reserve URL tag in your HTML templates can just be {% url 'url_pattern_name' %}
The tag you were first using {% url 'inventory:render_results' %}. Indicates that Django is to go to your URL conf, find the namespaced urls ie. app_name = 'inventory'. Then search in the namespace to find render_results. You can use either configuration but again the latter is stating your URL is namepspaced with app_name='inventory'.
I am not entirely sure if you can use the non-namespaced HTML tag {url 'url_pattern_name'%} with a namespace url config ex.
https://docs.djangoproject.com/en/3.0/topics/http/urls/#reversing-namespaced-urls

how do i create a profile page that shows all users post to the user and to other users

am new to Django and am trying to create a blog site where users can sign up and post articles, but my problem is how can I display a user's post on the user's profile page so that when other users reading the post clicks on the author's name it takes them to the post.author's profile page with the post.author's recent post listed and not the request.user's post. here is my code.
here is accounts/views.py
views.py
#login_required()
def user_profile_view(request, username):
post = User.objects.filter(courses__author=username)
context = {'courses': courses}
return render(request, 'accounts/user_profile_view.html', context)
and here is post/models.py
models.py
class Posts(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
cover = ProcessedImageField(upload_to='post_featured_image',
processors=[ResizeToFill(600, 300)],
format='png',
options={'quality': 80},
blank=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
body = models.TextField()
summary = models.TextField(max_length=200)
here is the template
post_list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="col-lg-6">
{% for course in courses_list %}
<div class="central-meta item">
<div class="user-post">
<div class="friend-info">
{% if post.author.profile.avatar %}
<figure>
<img src="{{ post.author.profile.avatar.url }}" alt="">
</figure>
{% else %}
<img src="{% static 'default.ico' %}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.author.get_full_name|title }}</ins>
<span>published: {{ post.published }}</span>
</div>
<div class="post-meta">
{% if course.cover %}
<img src="{{ post.cover.url }}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.title|title }}</ins>
</div>
<div class="description">
<p><span>{{ post.summary|capfirst }}</span></p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
here is my accounts/urls.py
urls.py
app_name = 'accounts'
urlpatterns = [
path('accounts/profile/<str:username>/', user_profile_view, name='user_profile'),
]
you should be able do that, easy and via lots of ways.
make a post model like this:
class Post(models.Model):
author = foreign_key(User, related_name="posts", on_delete=models.CASCADE)
title = char_field()
content ........
so with that related name you will be able to reverse from user to its posts too!.
in your template do this:
{{ post.author }}
this link will redirect user to the posts author dashboard if you arrange the urls pattern correctly.
then for sorting authors posts, you have to pass the dashboard_owner to the template and use this name instead of user which normally will refer to the request.user -> user who are visiting the page
{% for post in dash_owner.posts.all %}
<li> <a href="{{ post.get_abslute_url }}" target="_blink">
{{ post.title }} </a> </li>
{% endfor %}
in views.py
def dashboard(request, owner_id=None)
if owner_id:
dash_owner = get_or_404(User, id=owner_id)
elif request.user.is_authenticated:
dash_owner = User.objectd.get(id=request.user.id)
return render(request, 'dashboard.html', {'dash_owner': dash_owner})
in urls.py -> urlpatterns:
path('dashboard/<int:owner_id>/', views.dashboard, name="dashboard")
this is the idea behind that, but for get the better result, you may need to clearly define the get_absolute_url of User model, to give you the url which machts to
'dashboard/<int:id/'
or another way is instead of that, do this:
{{ post.author }}

How to render template after failed form validation?

urls.py:
urlpatterns = [
path('employee/add_employee/', views.add_employee, name='add-employee'),
path('employee/add_employee/add/', views.add_employee_action, name='add-employee-action'),
]
I have add-employee page and some forms to fill there.
views.py:
def add_employee(request):
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
def add_employee_action(request):
if request.method == "POST":
personal_form = PersonalEmployeeForm(request.POST)
history_form = EmployeeHistoryForm(request.POST)
if personal_form.is_valid() and history_form.is_valid():
# here is some logic with models
return redirect('add-employee')
else:
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
template:
<form id="a-submit-form" action="add/" method="POST">
{% csrf_token %}
<div class="column-wrapper">
<div class="column">
<div class="form-wrapper">
{% for field in personal_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
<div class="column">
<div class="form-wrapper">
{% for field in history_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
</div>
<div class="button-bar-wrapper">
<div class="button_bar">
<a class="a-button positive" id="submit">Добавить</a>
<a class="a-button" href="{% url 'employee' %}">Сотрудники</a>
<a class="a-button" href="{% url 'index' %}">На главуную</a>
</div>
</div>
</form>
Submitting by <a> element is tested and worked well with jQuery script.
The problem is after submitting invalid forms I have a page with blah-blah/employee/add_employee/add/ URL. And if I try to submit forms again I have a page with blah-blah/employee/add_employee/add/add/ URL, which is incorrect. How can I render the page with blah-blah/employee/add_employee/ URL and show all error messages?
This is likely because you have written a relative URL in the <form> tag of the sections/add_employee.html template. The template thus contains something like:
<form method="post" action="add/">
...
</form>
You can use a URL with the {% url … %} template tag [Django-doc]:
<form method="post" action="{% url 'add-employee-action' %}">
...
</form>
Furthermore one usually uses the same path to handle both the GET and the POST request. So in fact you might simply remove the 'add-employee' path.

Completely stripping certain HTML Tags in Django forms

I have a ModelForm that posts news items to a database, and it uses a javascript textarea to allow the authorized poster to insert certain pieces of HTML to style text, like bold and italics. However, since I have the template output using the "safe" filter, it outputs all the HTML the form widget tries to pass on. This includes a bothersome <br> tag that never goes away, making it so you can submit without form validation reading the field as empty and stopping you. How can I make that I can not only filter the <br> tag, but completely remove it from the data? Here is relevant code:
Models.py:
from django.db import models
from django.forms import ModelForm, forms
from django.contrib.auth.models import User
# Create your models here.
class NewsItem(models.Model):
user = models.ForeignKey(User)
date = models.DateField(auto_now=True)
news = models.TextField(max_length=100000, blank=False, help_text='HELP TEXT')
def __unicode__(self):
return u'%s %s %s' % (self.user, self.date, self.news)
class NewsForm(ModelForm):
class Meta:
model = NewsItem
exclude=('user','date',)
Views.py:
from news.models import NewsForm, NewsItem
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
def news(request):
if request.method == 'POST':
item = NewsItem(user=request.user)
form = NewsForm(request.POST, instance=item)
if form.is_valid():
form.save()
return HttpResponseRedirect('/news/')
else:
form = NewsForm()
news_list = NewsItem.objects.all()
return render(request, 'news_list.html', {'news_list': news_list, 'form': form})
news_list.html:
{% extends "base.html" %}
{% block title %}News in the Corps{% endblock %}
{% block content %}
<h2 id="page_h">News in the Corps</h2>
{% if user.is_authenticated %}
<h3>Post News</h3>
<script src="{{ STATIC_URL }}nicEdit.js" type="text/javascript"></script>
<script type="text/javascript">bkLib.onDomLoaded(nicEditors.allTextAreas);</script>
<div id="news_poster">
<form id="news_poster" action="/news/" method="POST">{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
</div>
{% endif %}
<ul id="events_list">
{% if news_list %}
<div id="news_list">
{% for news in news_list %}
{% if news.id == 1 %}
<hr />
{% endif %}
<div id="{{ news.id }}" class="news_item">
<p class="poster">Posted By: {{ news.user }} | Posted On: {{ news.date }} | Link</p>
<div id="news_item">
{{ news.news|safe }}
</div>
</div>
<hr />
{% endfor %}
</div>
{% endif %}
</ul>
{% endblock %}
You can try the removetags template filter:
{{ news.news|removetags:"br"|safe }}
I can't help but thinking that the "removetags" as Timmy O'Mahony suggested might work if it was structured like this:
{{ news.news|safe|removetags:"br"}}
Give it a shot and see if it works. I would reply, but my karma's not height enough to directly reply to an answer with a suggestion.