Django invoice model formset - javascript

I am trying to create an invoice form. I am trying to use a formset because the products will be added more than once in the sales process. I am constantly failing in form creation.
My Models:
class Fatura(models.Model):
musteri = models.ForeignKey(CariModel, on_delete=models.CASCADE, blank=False)
fatura_tarihi = models.DateField(auto_now=True, blank=False)
fatura_numarasi = models.CharField(max_length=36, default=fatura_numarasi)
odeme_tarihi = models.DateField(auto_now=False, blank=True)
def __str__(self):
return "{} - {}".format(self.musteri, self.fatura_numarasi)
class FaturaUrunler(models.Model):
fatura = models.ForeignKey(Fatura, on_delete=models.CASCADE, blank=False)
baslik = models.CharField(max_length=128, blank=False)
urun = models.CharField(max_length=128, blank=False)
miktar = models.DecimalField(max_digits=12, decimal_places=3, default=1)
fiyat = models.DecimalField(max_digits=12, decimal_places=3)
vergi = models.CharField(choices=KDV, default=18, max_length=5)
My Views:
def index(request):
class GerekliFormlar(BaseFormSet):
def __int__(self, *args, **kwargs):
super(GerekliFormlar,self).__init__(*args, **kwargs)
self.queryset = Fatura.object.none()
UrunlerFormset = formset_factory(UrunForm, max_num=0, formset=GerekliFormlar)
if request.method == 'POST':
fatura_form = FaturaForm(request.POST)
urunler_formset = UrunlerFormset(request.POST, request.FILES)
if fatura_form.is_valid() and urunler_formset.is_valid():
fatura = fatura_form.save()
for form in urunler_formset.forms:
urunler = form.save()
urunler.fatura = fatura
urunler.save()
return HttpResponse("tesekkürler")
else:
fatura_form = FaturaForm()
urunler_formset = UrunForm()
c = {
'fatura_form': fatura_form,
'urunler_formset': urunler_formset
}
c.update(csrf(request))
return render_to_response('anasayfa_gecici.html', c)
I would like to make customer selection and product addition within the form. Simple billing system

In your view you were instantiating a form UrunForm() for GET requests and a formset UrunlerFormset() for POST requests. You should use a UrunlerFormset in both cases.
if request.method == 'POST':
fatura_form = FaturaForm(request.POST)
urunler_formset = UrunlerFormset(request.POST, request.FILES)
...
else:
fatura_form = FaturaForm()
urunler_formset = UrunlerFormset()

Related

form.errors is not returning bad request

Upon submitting a form, the desired outcome is to display validation error messages in the template if the form is not valid. When it comes to what I'm actually getting and the form doesn't catch the errors (I have Max_length = 240... doesn't catch an error when text is > 240).
forms.py:
from django import forms
from .models import Postit
MAX_POST_LENGTH = 240
class PostForm(forms.ModelForm):
class Meta:
model = Postit
fields = ['content']
def valid_content(self):
content = self.validated_data.get("content")
if len(content) > MAX_POST_LENGTH:
raise forms.ValidationError("This message is too long")
return content
views.py:
from django.http import HttpResponse, Http404, JsonResponse
from django.shortcuts import render, redirect
import random
from django.utils.http import url_has_allowed_host_and_scheme
from .forms import PostForm
from .models import Postit
# Create your views here.
def homepage_view(request, *args, **kwargs):
return render(request, 'pages/home.html', context={}, status=200)
# create a new post and add to database
def post_create_view(request, *args, **kwargs):
form = PostForm(request.POST or None)
next_url = request.POST.get('next') or None # pass next_url to respones
if form.is_valid():
obj = form.save(commit=False)
obj.save()
if request.headers.get('X-Requested-With' or
"HTTP_X_REQUESTED_WITH") == 'XMLHttpRequest':
return JsonResponse(obj.serialize(),
status=201) # testing if ajax is true
if next_url is not None and url_has_allowed_host_and_scheme(next_url, 'localhost'):
# if next_url invalid, no redirect - and check if safe
return redirect(next_url)
form = PostForm()
if form.errors:
if request.headers.get('X-Requested-With' or
"HTTP_X_REQUESTED_WITH") == 'XMLHttpRequest':
return JsonResponse(form.errors, status=400)
return render(request, 'comp/form.html', context={"form": form})
def postit_list_view(request, *args, **kwargs):
"""
REST API VIEW
return json data
"""
query_set = Postit.objects.all()
post_list = [x.serialize() for x in query_set]
data = {
"isUser": False,
"response": post_list
}
return JsonResponse(data)
def postit_detail_view(request, postit_id, *args, **kwargs):
"""
REST API VIEW
return json data
"""
data = {
"id": postit_id,
}
status = 200
try:
obj = Postit.objects.get(id=postit_id)
data['content'] = obj.content
except:
data['message'] = "Not found"
status = 404
return JsonResponse(data, status=status)
# json.dumps content_type='application/json'
template view:
{% extends 'base.html' %}
{% block head_title %}
- now!
{% endblock head_title%}
{% block content %}
<div class='row text-center'>
<div class='col'>
<h1>Welcome to Shareit</h1>
</div>
</div>
<div class='row mb-4'>
<div class='col-10 col-md-4 mx-auto'>
<form class='form' id='create-post-form' method='POST' action='/create-post'>
{% csrf_token %}
<input type='hidden' value="/" name="next"/>
<textarea required="required" class='form-control' name="content" placeholder="Post message here..."></textarea>
<button type='submit' class="btn btn-primary">Post</button>
</form>
</div>
</div>
<div class='row' id ='posts'>
Loading...
</div>
<script>
function handleCreatePostFormDidSubmit(event) {
event.preventDefault()
const myForm = event.target
const myFormData = new FormData(myForm)
const url = myForm.getAttribute("action")
const method = myForm.getAttribute("method")
const xhr = new XMLHttpRequest()
const responseType = "json"
xhr.responseType = responseType
xhr.open(method, url)
xhr.setRequestHeader("HTTP_X_REQUESTED_WITH", "XMLHttpRequest")
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
xhr.onload = function() {
if (xhr.status === 201) {
const newPostJson = xhr.response
console.log(newPostJson.likes)
const newPostElement = formatPostElement(newPostJson)
console.log(newPostElement)
const ogHtml = postElementContainer.innerHTML
postElementContainer.innerHTML = newPostElement + ogHtml
myForm.reset()
}
}
xhr.send(myFormData)
}
const createPostFormEl = document.getElementById("create-post-form")
createPostFormEl.addEventListener("submit", handleCreatePostFormDidSubmit)
const postElementContainer = document.getElementById("posts")
function loadPosts(postElement) {
// dynamically receive the request
const xhr = new XMLHttpRequest()
const method = 'GET'
const url = "/postit"
const responseType = "json"
xhr.responseType = responseType
xhr.open(method, url)
xhr.onload = function() {
const serverResponse = xhr.response
const listedItems = serverResponse.response // array of response
var finalPostStr = ""
var i;
for (i=0; i<listedItems.length; i++) {
var postObj = listedItems[i]
var currentItem = formatPostElement(postObj)
finalPostStr += currentItem
}
postElement.innerHTML = finalPostStr
}
xhr.send()
}
loadPosts(postElementContainer)
function handleLiked(post_id, currentCount) {
console.log(post_id, currentCount)
}
function LikeBtn(post){ // like button that receives post id and number of likes
return "<button class ='btn btn-primary btn-sm' onclick=handleLiked(" +
post.id + ","+ post.likes + ")>" + post.likes +" Likes</button>"
}
function formatPostElement(post){
var formattedPost = "<div class='col-12 col-md-10 mx-auto border py-3 mb-4' post id='post-" + post.id
+ "'><p>" + post.content +
"</p><div class ='btn-group'>" + LikeBtn(post) +
"</div></div>"
return formattedPost
}
</script>
{% endblock content %}
The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute.
So in your case your need to use clean_content(self), this is not up to you.
If you have a title attribute then clean_title(self), you get the idea !

Serve file with Flask's send_file then redirect to another page

I want to download a file and at the same time redirect to a new page. The user is shown a page with a link for the download. When they click it, I want to start the download then redirect to another page so they can't keep clicking it. However, I can only seem to get one or the other to work.
from flask import Flask, render_template, redirect, url_for, session, request, flash, send_file
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, BooleanField
from pytube import YouTube
import os
import random, string
import re
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
session_id = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
class url_form(FlaskForm):
link = StringField('Enter link of YouTube video you would like to convert...')
audio = BooleanField('Audio Only')
submit = SubmitField('Convert')
def download_video(link, just_audio):
yt = YouTube(link)
download_path = 'conversions/'
#global myvar
if just_audio == True:
stream = yt.streams.filter(only_audio=True).first()
tag = 'video'
else:
stream = yt.streams.filter(adaptive=True).first()
tag = 'audio only'
download_video.name = yt.title
download_video.cleanString = re.sub('[^a-zA-Z0-9 \n\.]', '', download_video.name)
download_video.thumbnail = yt.thumbnail_url
download_video.path = stream.download(filename = download_video.cleanString, output_path = download_path)
return
#app.route('/', methods=['GET', 'POST'])
def index():
result = False
form = url_form()
if form.validate_on_submit():
session['link'] = form.link.data
if form.audio.data:
just_audio = True
else:
just_audio = False
session['just_audio'] = just_audio
link = session.get('link')
just_audio = session.get('just_audio')
download_video(link, just_audio)
#download_video(link, just_audio)
#return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return redirect(url_for('conversion_complete'))
return render_template('index.html', form=form, result=result)
#app.route('/conversion_complete', methods=['GET', 'POST'])
def conversion_complete():
return render_template('conversion_complete.html')
#app.route('/download/', methods=['GET'])
def download():
return send_file(download_video.path, attachment_filename=download_video.cleanString + '.mp4', as_attachment=True)
return render_template('result.html')
<html>
<body>
<h1>Conversion Complete</h1>
<a href='download' target='blank' type='button'><button class='btn btn-default'>Download!</button></a>
</body>
</html>

Trying to send an array to django database but get an error say Method not allow

I'm new to Django. I'm working on an app where the user types in the name of the activities and the times. It then displays it as a graph. When the user saves it, the data will end up being in a JSON format through serialization. My problem right now is that it only save the last value of the user input and not all the input. I'm trying to store an array into the Django database. I found multiple answers but none help. I figure to maybe make an HTTP request to send the value but any alternative will due.
view.py
from django.shortcuts import render
from django.core import serializers
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_protect
from page.templates.forms import ActivitiesForm
from page.models import Activities
from .serializers import ActivitiesSerializer
from rest_framework.parsers import JSONParser
from rest_framework.decorators import api_view
from rest_framework.decorators import parser_classes
from rest_framework.response import Response
#api_view()
def page_list(request):
if request.method == 'GET':
activities = Activities.objects.all()
serializer = ActivitiesSerializer(activities, many=True)
return Response(serializer.data)
elif request.method == 'POST':
# data = JSONParser().parse(request)
serializer = ActivitiesSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
#csrf_protect
def page_detail(request, pk):
try:
activities = Activities.objects.get(pk=pk)
except Activities.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = ActivitiesSerializer(activities)
return JsonResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = ActivitesSerializer(activities, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
activities.delete()
return HttpResponse(status=204)
#csrf_protect
def page_show_view(request):
a = Activities.objects.all()
activities = serializers.serialize("json", a)
return render(request, "page_show_view.html", {'activities':a})
def home_view(request, *args, **kargs):
form = ActivitiesForm(request.POST or None)
# context_instance=RequestContext(request)
if form.is_valid():
form.save()
context = {
'form': form
}
return render(request, "home_view.html", context)
models.py
from base.models import CommonInfo
# Create your models here.
class Activities(CommonInfo):
activity = models.CharField(max_length = 15)
time = models.CharField(max_length = 15)
serializers.py
from .models import Activities
class ActivitiesSerializer(serializers.ModelSerializer):
activity = serializers.CharField(max_length = 15)
time = serializers.CharField(max_length = 6)
def create(self, validated_data):
return Activities.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.activity = validated_data.get('activity', instance.activity)
instance.time = validated_data.get('time', instance.time)
return instance
class Meta:
model = Activities
fields = ('activity', 'time')
urls.py
from django.urls import path
from page import views
urlpatterns = [
path('page/', views.page_list),
path('page/<int:pk>/', views.page_detail),
]
home_view.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<main>
<div>
<h1>Time Management</h1>
<form action='/page/'method='POST' autocomplete="off" enctype="multipart/form-data" >{% csrf_token %}
{{form.as_p}}
<select name="" id="Time">
<option value="Select" default>Select time</option>
<option value="Hours" id="hours">Hours</option>
<option value="Min" id="Min">Minutes</option>
</select>
<br>
<br>
<input type="button" id="ActivityButton" value="Add Activity" onclick="addValue()">
<input type="submit" id="ActivityButton" value="Save">
</form>
</div>
</main>
<script src="{% static 'js/app.js' %}"></script>
{% endblock %}
app.js
let hour = 24
// declare chart variable and dataSet variable
var chart, dataSet;
anychart.onDocumentLoad(function () {
// create an instance of a pie chart
chart = anychart.pie();
// create dataSet and add some initial data
dataSet = anychart.data.set(["Undocumented time", hour]);
// set the inital data
chart.data(dataSet);
chart.innerRadius("30%");
chart.background().fill({
keys: ["whitesmoke"]
});
// set the container element and draw
chart.container("container").draw();
// create and configure a label
var label = anychart.standalones.label();
label.text("Activities");
label.width("100%");
label.height("80%");
label.fontColor("white");
label.hAlign("center");
label.vAlign("middle");
// set the label as the center content
chart.center().content(label);
});
// set data to chart when user performs an action
function addValue(){
var minPerc = 60
var minCalc;
// read values from inputs
var name = document.getElementById('id_activity').value;
var value = document.getElementById('id_time').value;
var option = document.getElementById('Time').value;
// appendn name value pair to dataSet
if(hour > 0){
if(option == "Min"){
//Set hour
minCalc = value / minPerc
hour = hour - minCalc;
dataSet.row(1, ["Undocumented time", hour])
dataSet.append([name, minCalc]);
}
else if(option == "Hours"){
hour = hour - value;
dataSet.row(1, ["Undocumented time", hour])
dataSet.append([name, value]);
}
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://localhost:8000/page/", true);
xhttp.setRequestHeader('X-CSRFToken', csrftoken);
xhttp.setRequestHeader("Content-Type", "application/json; charset=utf8");
xhttp.setRequestHeader('Accept', 'application/json');
xhttp.send(JSON.stringify(dataSet.jc))
console.log(dataSet.jc)
}
}
Question:
Keep getting error message say method not allowed: /page/error message
Any alternative is very appreciated.
See #api_view() docs.
By default only GET methods will be accepted. You need to change your line to:
#api_view(['GET', 'POST'])
def page_list(request):
# your code here

How to update image input with django forms and template

I have a django project where a user has a profile and can upload a profile picture. The models.py is:
`class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64,blank=True)
profilePic = models.ImageField(blank=True, null=True, upload_to= "profile/")
phoneNumber = models.CharField(max_length=12,blank=True)
streetAddress = models.CharField(max_length=64,blank=True)`
On my site, the user can edit his profile including the profile picture. To do so, I have a form, where the initial values are the ones initially stored. The forms.py is:
class EditProfile(forms.ModelForm):
def __init__(self, profile, *args, **kwargs):
self.profile = profile
super(EditProfile, self).__init__(*args, **kwargs)
self.fields['name'] = forms.CharField(label='Name:', initial= profile.name,required=False)
self.fields['phoneNumber'] = forms.CharField(label= "Phone Number:", initial= profile.phoneNumber,required=False)
self.fields['streetAddress'] = forms.CharField(label='Street Address and/or Postal Code:', initial= profile.streetAddress,required=False)
self.fields['profilePic'] = forms.ImageField(label='Profile Picture:', initial= profile.profilePic,required=False)
class Meta:
model = Profile
fields = ("name", "phoneNumber","streetAddress", "profilePic")
This part works great, and on my site I can see the stored values. The problem is when I try to edit them and submit the form.
My views.py is:
def settings(request):
user= request.user
if request.method == 'GET':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
return render(request, 'listings/settings.html', {'form': f1,'form2': f2})
elif request.method == 'POST':
userProfile = Profile.objects.get(user=user)
f1= UserProfile(user=request.user)
f2= EditProfile(profile=userProfile)
name= request.POST["name"]
phoneNumber = request.POST["phoneNumber"]
streetAddress = request.POST["streetAddress"]
Profile.objects.filter(user=user).update(name= name, phoneNumber = phoneNumber, streetAddress = streetAddress)
if "profilePic" in request.FILES:
image1=request.FILES["profilePic"]
fs1=FileSystemStorage()
fs1.save(image1.name, image1)
userProfile.profilePic = image1
userProfile.save()
else:
userProfile.profilePic.delete()
messages.success(request, 'Your profile has been updated!')
return redirect("/settings")
Everything gets edited with no issues except for the imageFile. If I upload the file, it works and the image is updated. However, if I make no changes to the imageFile (i.e. I want to keep the same image), the request.FILES is empty, and then the code goes to the else statement and deletes the existing profilePic.
My question is that the I can see the initial profile picture on my site, so the forms.py is working, but why isn't it being submitted along with the rest of the form?
Your question is a bit confusing, but it seems that you are trying to reinvent the wheel. If you want to have the "initial" data reinserted into the form, you should use the native instance parameter. You can use it as such:
profile = Profile.objects.get(user=user)
# This can be in your GET
profile_form = EditProfile(instance=profile)
# This can be in your POST
profile_form = EditProfile(request.POST, request.FILES, instance=profile)
profile_form.save()

Integrating Flask-Python with HTML and JavaScript

In my code , I want the Javascript defined in index.html page to run when a particular condition in app.py is true, else the script should not run. How can I achieve this?
app = Flask(__name__)
#app.route('/',methods=["GET","POST"])
def index():
#print "came here"
if request.method == 'POST':
search_token = request.args.get("validationtoken")
print "search", search_token
if search_token != None:
# text = search_token
resp = Response(search_token, status=200, mimetype='plain/text')
print "resp",resp
return resp
else:
print " Notification received "
##### HERE I NEED TO CALL THE Java SCRIPT DEFINED IN HTML PAGE TO EXECUTE
elif request.method=="GET":
code=request.args.get('code')
state=request.args.get('state')
----
pls help..
The python script should go like this
app = Flask(__name__)
#app.route('/',methods=["GET","POST"])
def index():
script = False
if request.method == 'POST':
search_token = request.args.get("validationtoken")
print "search", search_token
if search_token != None:
# text = search_token
resp = Response(search_token, status=200, mimetype='plain/text')
print "resp",resp
return resp
else:
print " Notification
script = True
render_template('index.html', Script=script)
elif request.method=="GET":
code=request.args.get('code')
state=request.args.get('state')
----
And the index.html should be something like this
{% if Script %}
<script type="text/javascript">
"Your code lies here"
</script>
You can pass the variable in your python script (Your app) to the index.html template using this way as Flask uses Jinja templates.

Categories

Resources