I have a code and the thing I am not understanding is why a function of some_view in views.py is not fetching files from CSV. Is there something wrong? There is also html file by the name of index.html. I want it to fetch the first column of CSV and make a loop in html so that I don't have to repeat it every time.
views.py
def some_view(request):
reader = csv.DictReader(open('file.csv','r'))
csv_output = []
data = csv.reader(reader)
for row in data:
csv_output.append(row)
return render(request, 'index.html', context={'csv_content': csv_output})
index.html
{% for content in csv_content %}
<div class="row">
{% for k in content.items %}
<div class="column">
<p> value is {{v}} </p>
</div>
{% endfor %}
</div>
{%endfor%}
Related
I'm building a news aggregator. I am connected to the twitter and reddit APIs through the tweepy and PRAW libraries. I'm pulling json data from twitter and reddit, and displaying posts in a timeline format side by side.
I have one template called main.html which takes in context(reddit post ids; twitter status urls) and passes that context to template tags, in order to generate html to embed. Here is the template where all this work is being done. The template tags are 'tweet_tags.py' and 'red_attempt.py' as you can see loaded at the top of the page.
{% block content %}{% load red_attempt %} {% load tweet_tags %} {% autoescape off %}
<h1>Welcome</h1>
Refresh News
<div class="container">
<div class="row">
<div class="col-6">
<h3 class='text-center'>Reddit News</h3>
{% for item in reddit %}
<div class="mdl-card__media" id="timeline"></div>
{% red_attempt item %}
<br>
{% endfor %}
</div>
<div class="col-6">
<h3 class='text-center'>Twitter News</h3>
{% for item in twitter %}
<div class="mdl-card__media" id="timeline"></div>
{% tweet_tags item %}
<br>
{% endfor %}
</div>
</div>
</div>
{% endautoescape %}{% endblock %}
The template tags are 'tweet_tags.py' and 'red_attempt.py' as you can see loaded at the top of the page.
Here is their code, respectively:
tweet_tags.py
def tweet_tags(url):
""" Requests a tweet from oembed and returns the html element """
tweet_request = requests.get(
'https://publish.twitter.com/oembed?url=' + url + '&omit_script=true')
tweet_json = tweet_request.json()
tweet_html = tweet_json['html']
return tweet_html # returns to our template
red_attempt.py
def red_attempt(url):
""" Requests a tweet from oembed and returns the html element """
headers = {
'User-Agent': 'nba_comp app',
'From': 'nickiscool88',
'Accept': 'application/json'
}
endpoint = requests.get(
f"https://www.reddit.com/oembed?url=https://www.reddit.com{url}", headers=headers)
return endpoint.json()['html']
This all works as expected.
What I want to do, is instead, have a services script pull the twitter and reddit data, store that data in my database with models.py then pull the data from the local database to display. I'm trying to do that in this script, test.html
{% block content %} {% autoescape off %}
{% for post in all %}
<div class="mdl-card__media" id="timeline"></div>
<p>{{ post.html }}</p>
</div>
{% endfor %} {% endautoescape %}{% endblock %}
In this case, "all" is the context, which is a database object from models.py. Here is my models.py script.
class Post(models.Model):
post_type = models.CharField(
max_length=20, null=True, blank=True)
root_url = models.CharField(max_length=200, default="", unique=True)
html = models.TextField(default="")
created_at = models.DateTimeField(auto_now_add=True)
So as you can see, I'm trying to loop through all the posts in my database, and post the html of each post. I'm expecting the same result as main.html, but instead, it looks like this
as opposed to main.html which looks like this
All the script/widget tags that support embedding are at the bottom of the HTML templates.
How can I display these twitter/reddit posts from my database in test.html similar to how I can display them like main.html, where I'm just fetching the json data?
Issue solved. The script tags used for embedding twitter/reddit posts needs to be inside the tag.
I am displaying django models on one of my website's pages. When I press one's ImageField on the page, I want it to open another page including only that one object. How do I do that ?
I thought about using the filter method in my views.py for filtering through my objects and finding that exact one, but I don't know what arguments to use.
Any ideas? (I am a beginner in django)
VIEWS.PY
from django.shortcuts import render
import requests
from . import models
def index(request):
return render(request, 'base.html')
def new_search(request): ********NOT IMPORTANT (I THINK)********
search = request.POST.get('search')
models.Search.objects.create(search=search)
objects = models.Object.objects.all()
results = objects.filter(name__contains=search).all()
args = { 'results': results }
return render(request, "my_app/new_search.html", args)
def individual_page(request):
link = request.GET.get('object-link')
objects = models.Object.objects.all()
return render(request, "my_app/individual_page.html")
MY TEMPLATE
{% extends "base.html" %}
{% block content %}
{% load static %}
<h2 style="text-align: center">{{ search | title }}</h2>
<div class="row">
{% for result in results %}
<div class="col s4">
<div class="card medium">
<div class="card-image">
<a name="object-link" href="{% url 'individual_page' %}"><img src="{{ result.image.url }}" alt=""></a>
</div>
<div class="card-content">
<p>{{result.name}}</p>
</div>
<div class="card-action">
View listing: Price TEST
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
So, the thing I want to do is: when I press the anchor tag that includes the image, I get redirectioned to another page which contains only that one object's info.
I want to have an download button a html page that renders a django table.
I followed the documentation of django2 and this post How to export .csv with Django-Tables2? was helpful but could not make the trick.
I feel like I have done everything correctly (according to my beginner skills), there is no error but the download button is not there.
I was wondering if someone has any help to provide on this one
table.py
class AnormalTable(tables.Table):
class Meta:
model = stock_anormal
template_name = "django_tables2/bootstrap4.html"
export_formats = ['csv', 'xlsx']
view.py
#method_decorator(login_required, name='dispatch')
class PostDetailalerte_negat(LoginRequiredMixin,APIView, tables.SingleTableMixin, ExportMixin):
def get(self, request):
queryset = stock_negatif.objects.all()
table = NegatTable(queryset)
RequestConfig(request).configure(table)
export_format = request.GET.get("_export", None)
if TableExport.is_valid_format(export_format):
exporter = TableExport(export_format, table)
return exporter.response("table.{}".format(export_format))
return render(request, 'detailstocknegat.html', {'table':table})
html snipet
<div class="d-sm-flex align-items-center justify-content-between mb-4">
<h1 class="h3 mb-0 text-gray-800">ITEMS IN ALERTE SAFETY STOCK LEVEL</h1>
<div>
{% for format in view.export_formart %}
<i class="fas fa-download fa-sm text-white-50"></i> Generate Report
{% endfor %}
</div>
</div>
<table>
{% load django_tables2 %}
{% render_table table %}
</table>
I'm not sure if this will fix this specific problem but I ran into basically the same issue and this is how I solved it:
I moved the export_formats = ['csv', 'xlsx'] that was in table.py originally into the view for my table (view.py in this example). Then I passed export_formats directly to the html by changing the return code in views.py : return render(request, 'detailstocknegat.html', {'table':table, 'export_formats':export_formats}).
Then in the html for my table (html snipet in this example) I changed the for statement to be:
{%for format in export_formats %}>
<a href="{% export_url format %}">
download <code>.{{ format }}</code>
</a>
{% endfor %}
I hope this helps somebody out there!
Python: 2.7.11
Django: 1.9
I want to upload a csv file to Django and analyze it with a Python class. No saving is allowed and the file is only needed to reach the class to be analyzed. I'm using Dropzone.js for the form but I don't understand how I should configure/program the views to achieve this.
<form action="/upload/" method="post" enctype="multipart/form-data" class="dropzone" id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
I have found an article about this but it describes saving and is based on Django 1.5.
view.py
def upload(request):
if request.method == 'POST':
file = FileUploadForm(request.POST)
if file.is_valid():
return HttpResponseRedirect('/upload/')
else:
file = FileUploadForm()
return render(request, 'app/upload.html', {'file': file})
forms.py
from django import forms
class FileUploadForm(forms.Form):
file = forms.FileField()
Closing Update:
The most important difference between the helping answer and my situation is that I had to decode my input.
See the following line as mine csv_file in handle_csv_data:
StringIO(content.read().decode('utf-8-sig'))
Access the csv file in the view function. If you are using python 3, you must wrap the InMemoryUploadedFile in a TextIOWrapper to parse it with the csv module.
In this example the csv is parsed and passed back as a list named 'content' that will be displayed as a table.
views.py
import csv
import io # python 3 only
def handle_csv_data(csv_file):
csv_file = io.TextIOWrapper(csv_file) # python 3 only
dialect = csv.Sniffer().sniff(csv_file.read(1024), delimiters=";,")
csv_file.seek(0)
reader = csv.reader(csv_file, dialect)
return list(reader)
def upload_csv(request):
csv_content=[]
if request.method == 'POST':
csv_file = request.FILES['file'].file
csv_content = handle_csv_data(csv_file)
return render(request, 'upload.html', {'content':content})
Your original code did not use django's form framework correctly, so I just dropped that from this example. So you should implement error handling when the uploaded file is invalid or missing.
upload.html
<form action="/upload/"
method="post"
enctype="multipart/form-data"
class="dropzone"
id="dropzone">
{% csrf_token %}
<div class="fallback">
<input name="file" type="file"/>
<input type="submit"/>
</div>
</form>
{% if content %}
<table>
{% for row in content %}
<tr>
{% for col in row %}
<td>{{ col }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
I've added a 'submit' button so this works without the dropzone thing. I also removed 'multiple' from the file input, to keep the example simple. Finally there's a table if the template receives content from a parsed csv. But when using dropzone.js, you have to use a javascript callback function to display the table.
I'm trying to follow the Simple Blog tutorial at Django By Example. I've managed to get as far as producing a site that loads correctly, but while the index view is loading find, and the links to the individual posts show up and appear to be formatted correctly, they point back to the index template so all that happens when you click on them is that it reloads the index view. I'm new to Django and the tutorial is sparse to say the least and not helped by the fact it's written for an old version of Django and I'm using 1.5. I've been staring at it all afternoon and I'm pretty lost.
Here's my urls.py
from django.conf.urls import patterns, url
from blog import views
urlpatterns = patterns('blog.views',
#index
(r"$", 'main'),
#ex: /1/
(r"^(\d+)/$", 'post'),
#ex: /add_comment/1/
(r"^add_comment/(\d+)/$", 'add_comment'),
)
my views.py
from blog.models import Post, PostAdmin, Comment, CommentAdmin
class CommentForm(ModelForm):
class Meta:
model = Comment
exclude = ["post"]
def main (request):
"""Main Listing."""
posts = Post.objects.all().order_by("-created")
paginator = Paginator(posts, 10)
try: page = int(request.GET.get("page", '1'))
except ValueError: page = 1
try:
posts = paginator.page(page)
except (InvalidPage, EmptyPage):
posts = patinator.page(paginator.num_pages)
return render_to_response("blog/list.html", dict(posts=posts, user=request.user))
def post (request, pk):
"""single post with comments and comment form"""
post = Post.objects.get(pk=int(pk))
comments = Comment.objects.filter(post=post)
d = dict(post=post, comments=comments, form=CommentForm(), user=request.user)
d.update(csrf(request))
return render_to_response("blog/post.html", d)
and the list.html that contains the links that aren't going anywhere!
{% extends "blog/bbase.html" %}
{% block content %}
<div class="main">
<!-- Posts -->
<ul>
{% for post in posts.object_list %}
<div class="title">{{ post.title }}</div>
<ul>
<div class="time">{{ post.created }}</div>
<div class="body">{{ post.body|linebreaks }}</div>
<div class="commentlink">Comments</div>
</ul>
{% endfor %}
</ul>
<!-- Next/Prev page links -->
{% if posts.object_list and posts.paginator.num_pages > 1 %}
<div class="pagination" style="margin-top: 20px; margin-left: -20px; ">
<span class="step-links">
{% if posts.has_previous %}
newer entries <<
{% endif %}
<span class="current">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}
</span>
{% if posts.has_next %}
>> older entries
{% endif %}
</span>
</div>
{% endif %}
</div>
{% endblock %}
The Django URL resolver will return the first URL pattern that matches the incoming request. The regex for your 'main' view r"$" will match ANY incoming request since you are only looking for $ which is an end of string character.
You need to alter your 'main' URL regex to be r'^$'.
Alternatively, if you would like a catch-all view, you could move the 'main' view to the bottom of your URLs