Uploading to S3 from Django - html

I'm trying to add functionality to my Django site to upload files to an AWS S3 bucket. I found django-s3direct, which seems perfectly suited. After following all the setup instructions, though, I'm getting an error rendering the very basic HTML template:
<html>
<head>
<meta charset="utf-8">
<title>s3direct</title>
{{ form.media }}
</head>
<body>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
</form>
</body>
</html>
I get the error Reverse for 's3direct' not found. 's3direct' is not a valid view function or pattern name. on the line with {{ form.as_p }}.
In my urls.py I have (as specified in the s3direct docs):
from django.conf.urls import url
from .views import get_upload_params, generate_aws_v4_signature, MyView
app_name = 's3direct'
urlpatterns = [
url(r'^$', MyView.as_view(), name='form'),
url('^get_upload_params/', get_upload_params, name='s3direct'),
url('^get_aws_v4_signature/', generate_aws_v4_signature, name='s3direct-signing'),
]
In forms.py:
from django import forms
from s3direct.widgets import S3DirectWidget
class S3DirectUploadForm(forms.Form):
csv = forms.URLField(widget=S3DirectWidget(dest='csv_destination'))
And in views.py (along with a couple other long functions from s3direct):
from django.views.generic import FormView
from .forms import S3DirectUploadForm
class MyView(FormView):
template_name = 'form.html'
form_class = S3DirectUploadForm
I've configured an IAM policy and added keys to my Django settings file, as well as made a CORS policy for my S3 bucket. I'm using Django 2.0. I'm stuck on this reverse error, and can't seem to figure out what's causing it.

According to docs urls.py should contain
urlpatterns = [
url(r'^s3direct/', include('s3direct.urls')),
]

Related

Pass Jinja2 template as html string while rendering using FastAPI?

My template is as follows:
<!-- template1.html -->
<html>
<head>
<title>Item Details</title>
</head>
<body>
<p>{{ req }}</p>
</body>
</html>
To render the template I am using the following code:
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
app = FastAPI()
template = Jinja2Templates(directory="templates")
#app.get("/list_items")
def home(request: Request):
return template.TemplateResponse('template1.html',{"req": req})
#app.get("/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title></title>
</head>
<body>
<form action="/list_items">
<input type="text" placeholder="Search.." name="search">
<button type="submit">Search</button>
</form>
</body>
</html>
"""
But I do not want to use a separate folder with files for a simple template. How do I pass the html text instead of the function TemplateResponse
You can use HTMLResponse. Pass HTMLResponse as the parameter response_class of your route.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items", response_class=HTMLResponse)
def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
You can also override the response directly in your endpoint, by returning it.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items")
def read_items():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Update
Jinja2Templates.TemplateResponse expects as name parameter a filename that is pointing to the template your would like to return, and which lies in the Jinja2Templates directory you defined (e.g., Jinja2Templates(directory="templates") ). You can't pass the template contents to its place. Jinja2Templates will attempt to retrieve the file you passed using the directory you defined earlier, see here -> here -> here. Hence, what you are asking, it doesn't seem to be natively possible (but, with some hackish stuff maybe doable); however, there is nothing wrong with having a templates directory, even for small template files.

How to get a url param in a django template?

I need to get the param of the url inside a html file, but I need to know if is possible in a tag, or how can I get the url params using Class-based views?
My urls.py file
from django.urls import path
from .views import UsersView
urlpatterns = [
path('list/<int:pk>/', UsersView.as_view(), name='user_list'),
]
My html file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Users</title>
</head>
<body>
{{ request.GET.pk }}
</body>
</html>
You can use
self.kwargs['pk']
Inside a CBV to get the URL parameter, since there is a <int:pk>

image path is not identifiable on index.html of django3

i am following a tutorial based on django 2 and currently running version 3 of django, the problem i am facing is the identifying path of the tag on the front end of index.html, i'll post the code bellow , kindly tell me where i went wrong and any other mistakes
my settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS= (os.path.join(BASE_DIR, 'static'),) #static root added (A2)
MEDIA_ROOT=os.path.join(BASE_DIR, 'media')
MEDIA_URL='/media/'
my urls.py of main project
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('',include('posts.urls')),
path('user/',include('user.urls')),
path('admin/', admin.site.urls),
]+ static(settings.STATIC_URL, document_root=settings.MEDIA_ROOT)
my models.py of app
class Posts(models.Model): #created this model field
def min_len(val): #this is the custom validator working
if len(val)<=9:
raise validators.ValidationError("%(val)s Must be more than 10", params={'val':val})
title=models.CharField(validators=[min_len],max_length=255) #validation list provided
content=models.TextField(validators=[min_len])
thumb_nail=models.FileField(upload_to="posts/",null=True) #file field added
class Posts_Form(forms.ModelForm): #to build a form using django and not html
class Meta: #will get data of the fields=[] only
model=Posts
fields=['title','content','thumb_nail','user','category']
views.py
def index(request):
form=Posts_Form() #created form object
data=Posts.objects.all() #retrive data from the model to display
category=Category.objects.all() #we get all data of category
if request.method=='POST':
form=Posts_Form(request.POST,request.FILES) #request.FILES for file data
if form.is_valid():
# data=Posts(
# title=request.POST['title'],
# content=request.POST['content'],
# )
form.save()
return redirect('/')
return render(request,'index.html',{'title':'Add New Post','form':form,'rows':data,'categories':category})
and my index.html
{% extends "layout.html" %}
{% load static %}
{% block content%}
{%for row in rows%}
<h2>
{{row.title}}
</h2>
<p>
{{row.content}} - <small> {{row.created_at}}-{{row.user.username}} </small>
</p>
<p><img src="{%static 'row.thumb_nail.url' %}" alt="My image" width="150"> </p>
<p>{{row.category.all|join:", "}} </p>
{%endfor%}
</div>
and my layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width , initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>
{{title}}
</title>
<!--the below line is for the css bootstrap, from cdnjs official site-->
<!--link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/css/bootstrap.min.css"-->
</head>
<body>
{% block content %} {% endblock %}
</body>
</html>

Having two forms in one HTML page

I wanted to have a page for both sign up and login. However I couldn't handle the two forms. Here is my code.
I was wondering myself if it is possible to give names to the forms or handle it in another way?
forms.py
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
class Meta:
fields = ("username", "email", "password1", "password2")
model = get_user_model()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["username"].label = "Display name"
self.fields["email"].label = "Email address"
url.py
from django.conf.urls import url
from django.contrib.auth import views as auth_views
from . import views
app_name = 'accounts'
urlpatterns = [
url('', views.SignUp.as_view(), name="signup"),
url('', auth_views.LoginView.as_view(template_name="index.html"),name='login'),
url('', auth_views.LogoutView.as_view(), name="logout"),
]
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="container">
<h1>Login</h1>
<form method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-default">
</form>
</div>
<div class="container">
<h1>Sign Up</h1>
<form method="POST" >
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-default">
</form>
</div>
</body>
</html>
Thank You very much
I believe this post has the answer you need. Here are my thoughts on the information:
Put different URLs in the action for the two forms. Then you'll have two different view functions to deal with the two different forms. This will sometimes be a bit messy as some CBVs require a primary key and others do not, which may lead to conflicts.
Read the submit button values from the POST data. You can tell which submit button was clicked: How can I build multiple submit buttons Django form? This is the one that I prefer as it's cleaner to implement.
Actually i want able to POST and my apologies. in short you have to use Fetch API for this

angular get json from server but cannot display columns only whole model

So my problem is i can access json data from server but i dont know how to display them properly, until now i can only display all model and i would like to display only some data.
My template
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
{% verbatim %}
<body ng-app="MyApp">
<div ng-controller="MyPerson">
<div ng-repeat="person in person">
<p>{{person}}</p>
<p>{{persons.city}}</p>
<p>{{person.city}}</p>
<p>{{person.id}}</p>
<script>
var MyApp = angular.module('MyApp', []);
MyApp.controller('MyPerson', function($scope, $http) {
$http.get('http://127.0.0.1:8000/people/person/?format=json').
success(function(personData) {
$scope.person = personData;
});
});
</script>
</div>
</div>
{% endverbatim %}
</body>
</html>
My urls
from django.conf.urls import patterns, include, url
from people.views import *
from django.contrib import admin
from people.api import PersonResource
from tastypie.api import Api
from django.contrib.auth.decorators import login_required
person_resource = PersonResource()
urlpatterns = patterns('',
url(r'^$', IndexView.as_view(), name='home'),
url(r'^first/$', FirstView.as_view(), name='first'),
url(r'^admin/', include(admin.site.urls)),
url(r'^people/', include(person_resource.urls)),
)
My api
from people.models import Person
from tastypie.resources import ModelResource
class PersonResource(ModelResource):
"""
API Facet
"""
class Meta:
queryset = Person.objects.all()
resource_name = 'person'
My model
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=255)
city = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
parent = models.ForeignKey('Person', blank=True, null=True)
def __unicode__(self):
return "%s" % self.name
on terminal i get
[10/Dec/2014 18:38:20] "GET / HTTP/1.1" 200 797
[10/Dec/2014 18:38:20] "GET /people/person/?format=json HTTP/1.1" 200 420
and my html is
{"limit":20,"next":null,"offset":0,"previous":null,"total_count":3}
[{"city":"Budapest","id":1,"name":"Igor","resource_uri":"/people/job/person/1/","slug":"person"},{"city":"Warszawa","id":2,"name":"Karol","resource_uri":"/people/job/person/2/","slug":"person1"},{"city":"Jerozolima","id":3,"name":"Michal","resource_uri":"/people/job/person/3/","slug":"Ima"}]
So i can access json but it works only when i make ng-repeat person in persons
but then it only display data in these {{person}}
if i add sth else for example {{person.name}} it display nothing. I would like to display everything in nice format. I work on django and use rest Tastypie
If your JSON from http://127.0.0.1:8000/people/person/?format=json is coming back as an array then you need to change your $scope.person to be $scope.persons and your ng-repeat needs to read person in persons.