views.py
#login_required()
def Info_anlegen(request, id=None):
item = get_object_or_404(Kunden, id=id)
kontaktform_form = InfoForm(request.POST or None, instance=item)
if WindowsHome.objects.filter(KN=item.KN).exists():
item1 = WindowsHome.objects.get(KN=item.KN)
winform_form = InfoWinForm(request.POST or None, instance=item1)
if kontaktform_form.is_valid():
return redirect('/Verwaltung/KontaktAnlegen')
else:
form = acroniform(instance=item)
return render(request, 'blog/infokontakt.html',
{'kontaktform_form': kontaktform_form, 'winform_form': winform_form})
infokontakt.html
{% extends 'blog/base.html' %}
{% load bootstrap4 %}
{% block supertitle %} InfoPage {% endblock %}
{% block Content %}
{% load static %}
<html>
<div class="p-2 mb-1 bg-white text-black">
<head>
<div class="d-flex justify-content-center align-items-center container ">
<img src="{% static 'blog/Gubler.jpeg' %}" alt="Gubler" height="300" width="700">
</div>
</head>
<br>
<body>
<form class="form-row" action="" method="post">
<div style="margin-left: 2.5em;">
<font color="black">
<div class="col-sm-10 col-form-label">
{% csrf_token %}
{% bootstrap_form kontaktform_form %}
</div>
</font>
</div>
</form>
<form class="form-row" action="" method="post">
<div style="margin-left: 2.5em;">
<font color="black">
<div class="col-sm-10 col-form-label">
{% csrf_token %}
{% bootstrap_form winform_form %}
</div>
</font>
</div>
</form>
My Problem is:
if WindowsHome.KN exists it gets displayed
but if it does not exist i get the error
UnboundLocalError at /Verwaltung/InfoKontakt/6
local variable 'winform_form' referenced before assignment
Request Method: GET
Request URL: http://127.0.0.1:8000/Verwaltung/InfoKontakt/6
Django Version: 3.0.1
Exception Type: UnboundLocalError
Exception Value:
local variable 'winform_form' referenced before assignment
How do i say that if the db entry does not exist it should not display the form ?
OR
if the db entry does not exist just display a spacing " "
You try to send winform_form to your template but it is not set when WindowsHome.objects.filter(KN=item.KN).exists() is false.
You should probably do something like this:
#login_required()
def Info_anlegen(request, id=None):
context = {}
item = get_object_or_404(Kunden, id=id)
kontaktform_form = InfoForm(request.POST or None, instance=item)
if WindowsHome.objects.filter(KN=item.KN).exists():
item1 = WindowsHome.objects.get(KN=item.KN)
winform_form = InfoWinForm(request.POST or None, instance=item1)
context['winform_form'] = winform_form
if kontaktform_form.is_valid():
return redirect('/Verwaltung/KontaktAnlegen')
else:
form = acroniform(instance=item)
context['kontaktform_form'] = kontaktform_form
return render(request, 'blog/infokontakt.html', context)
You can initialize winform_form as None in the begining of your method, so that it will not throw that error. (i.e)
def Info_anlegen(request, id=None):
winform_form = None # Do like this
item = get_object_or_404(Kunden, id=id)
and also in your template you can use django template tags {% if %} ... {% endif %}
i.e
{% if winform_form %}
<form class="form-row" action="" method="post">
<div style="margin-left: 2.5em;">
<font color="black">
<div class="col-sm-10 col-form-label">
{% csrf_token %}
{% bootstrap_form winform_form %}
</div>
</font>
</div>
</form>
{% endif %}
Related
I am trying to retrieve the is_winning_bid value of a query set that returns:
<QuerySet [{'id': 33, 'user_id_id': 3, 'listing_id_id': 33, 'bid_amount': Decimal('13.00'), 'bid_time': datetime.datetime(2021, 4, 9, 16, 15, 9, 120168, tzinfo=<UTC>), 'is_winning_bid': False}]>
Views.py
#login_required(login_url="/login")
def listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing_id=listing_id)
user_id = request.user
# time_posted = Comment.time_posted
comments = Comment.objects.filter(listing_id=listing_id, user_id=user_id).order_by("-time_posted")
current_user = request.user
return render(request, "auctions/listing.html", {
"listing": listing,
"watchlist": Watchlist.objects.filter(user_id=request.user).count(),
"current_user": current_user,
"comments": comments,
"bids": bids.values()
})
template extract:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<div class="block my-3">
<div class="row my-1">
<div class="col-sm-2">
{{ bids }}
</div>
<div class="col-sm-4">
<strong>Number of bids:</strong> {{ listing.number_of_bids }}<br>
<strong>Starting Bid:</strong> {{ listing.starting_bid }}<br>
{% if listing.current_bid == 0 %}
<strong>Current Bid:</strong> <span class="current_bid">No Bid Yet!</span><br>
{% else %}
<strong>Current Bid:</strong> <span class="current_bid">{{ listing.current_bid }}</span><br>
{% endif %}
</div>
<div class="col-sm-5 text-center">
<form action="{% url 'auctions:bid' listing.id %}" method="post">
{% csrf_token %}
<input type="number" name="bid_amount" id="bid_input" required>
<button class="btn btn-primary" type="submit">Bid</button>
<br>
</form>
<a href="{% url 'auctions:add_to_watchlist' listing.id %}" style="background-color: black"
class="badge badge-secondary">
Add to Watchlist
</a>
<div class="col-sm-2"></div>
</div>
</div>
</div>
</body>
</html>
As I understand you want to retrieve only is_winning_bid values from database. To do so, look at the below codes.
In view:
bid_winnings = Bid.objects.filter(listing_id=listing_id).values('is_winning_bid')
In template:
{% for w in bid_winnings %}
{{ w.is_winning_bid }}
{% endfor %}
I am trying to create a edit form to update the database using Django model Forms but the problem is that edit form part of the sizeProductMap.html page is not rendering when edit form (sizeProductMap_edit) request is made.
My models are as shown below.
models.py
class Product(models.Model):
prod_ID = models.AutoField("Product ID", primary_key=True)
prod_Name = models.CharField("Product Name", max_length=30, null=False)
prod_Desc = models.CharField("Product Description", max_length=2000, null=False)
prod_Price = models.IntegerField("Product Price/Piece", default=0.00)
prod_img = models.ImageField("Product Image", null=True)
def __str__(self):
return "{}-->{}".format(self.prod_ID,
self.prod_Name)
class Size(models.Model):
size_id = models.AutoField("Size ID", primary_key=True, auto_created=True)
prod_size = models.CharField("Product Size", max_length=20, null=False)
def __str__(self):
return "{size_id}-->{prod_size}".format(size_id=self.size_id,
prod_size=self.prod_size)
class SizeProductMapping(models.Model):
size_p_map_id = models.AutoField("Size & Product Map ID", primary_key=True, auto_created=True)
size_id = models.ForeignKey(Size, null=False, on_delete=models.CASCADE, verbose_name="Size ID")
prod_id = models.ForeignKey(Product, null=False, on_delete=models.CASCADE, verbose_name="Product Id")
def __str__(self):
return ".`. {}_____{}".format(self.size_id,
self.prod_id)
This is the form I used to add and edit the model.
forms.py
from django import forms
from user.models import SizeProductMapping
class SizeProductMapForm(forms.ModelForm):
class Meta:
model = SizeProductMapping
fields = ['size_id', 'prod_id']
Here is the view I created to add ,update and delete the record.
views.py
def sizeProductMap(request):
form = SizeProductMapForm(request.POST, request.FILES)
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect("/admin1/sizeProductMap/")
else:
sizeProductMap_show = SizeProductMapping.objects.all()
# start paginator logic
paginator = Paginator(sizeProductMap_show, 3)
page = request.GET.get('page')
try:
sizeProductMap_show = paginator.page(page)
except PageNotAnInteger:
sizeProductMap_show = paginator.page(1)
except EmptyPage:
sizeProductMap_show = paginator.page(paginator.num_pages)
# end paginator logic
return render(request, 'admin1/sizeProductMap.html', {'sizeProductMap_show': sizeProductMap_show, 'form': form})
def sizeProductMap_delete(request, id):
sizeProductMap_delete = SizeProductMapping.objects.filter(size_p_map_id=id)
sizeProductMap_delete.delete()
return redirect('/admin1/productSizeMap')
def sizeProductMap_edit(request, id):
instance = SizeProductMapping.objects.get(size_p_map_id=id)
form = SizeProductMapForm(instance=instance)
if request.method == 'POST':
form = SizeProductMapForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return redirect('/admin1/sizeProductMap')
return render(request, 'admin1/sizeProductMap.html', {'form': form})
This is my urls.
urls.py
from django.urls import path
from admin1 import views
urlpatterns = [
path('sizeProductMap/', views.sizeProductMap, name="admin-size-product-map"),
path('sizeProductMap_delete/<int:id>', views.sizeProductMap_delete, name="admin-size-product-map-delete"),
path('sizeProductMap_edit/<int:id>', views.sizeProductMap_edit, name="admin-size-product-map-edit"),
]
This is the Html page where I want to display the form according to the page request.
sizeProductMap.html
{% extends 'admin1/layout/master.html' %}
{% block title %}Size Product Map{% endblock %}
{% block main %}
<h1>
<center>Size Product Map</center>
</h1>
<div class="container">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10">
{% if sizeProductMap_show %}
<button type="button" class="btn btn-primary mt-2" data-toggle="modal" data-target="#modal-primary">Add
Size Product Mapping
</button>
<div class="modal fade" id="modal-primary">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add Size Product Mapping</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
</div>
<div class="modal-body mt-2">
<form action="{% url 'admin-size-product-map'%}" method="POST"
enctype="multipart/form-data">
{% csrf_token %}
<table border="1" class="table table-bordered border border-info">
<tr>
<th>
{{form.size_id.label_tag}}
</th>
<td>{{form.size_id}}</td>
</tr>
<tr>
<th>
{{form.prod_id.label_tag}}
</th>
<td>
{{form.prod_id}}
</td>
</tr>
</table>
<input type="Submit" name="Submit" value="Submit" class="btn btn-success w-50"><br>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-outline-light" data-dismiss="modal">Close
</button>
</div>
</form>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<div class="container-fluid ">
<div class="row">
<div class="card mt-2 border border-secondary">
<div class="card-header">
<h3 class="card-title ">Size Product Map Table</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<table class="table table-bordered border border-info">
<thead>
<tr>
<th>Size Product Mapping Id</th>
<th>Product ID</th>
<th>Size ID</th>
<th>Action</th>
</tr>
</thead>
<tbody class="justify-content-center">
{% for x in sizeProductMap_show %}
<tr>
<td>{{x.size_p_map_id}}</td>
<td>{{x.prod_id}}</td>
<td>{{x.size_id}}</td>
<td><a href="{% url 'admin-size-product-map-edit' x.size_p_map_id %}"
class="btn btn-outline-primary mt-2"><i
class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
<a href="{% url 'admin-size-product-map-delete' x.size_p_map_id %}"
class="btn btn-outline-danger mt-2"><i
class="fa fa-trash" aria-hidden="true"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.card-body -->
<div class="card-footer clearfix ">
<ul class="pagination pagination-sm m-0 justify-content-center">
{% if sizeProductMap_show.has_previous %}
<li class="page-item"><a class="page-link"
href="?page={{sizeProductMap_show.previous_page_number}}">
Previous </a>
</li>
{% endif%}
{% for x in sizeProductMap_show.paginator.page_range %}
{% if sizeProductMap_show.number == x %}
<li class="page-item active"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% else%}
<li class="page-item"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% endif %}
{% endfor %}
{% if sizeProductMap_show.has_next %}
<li class="page-item"><a class="page-link"
href="?page={{sizeProductMap_show.next_page_number}}">
Next </a>
</li>
{% endif %}
</ul>
</div>
</div>
<!-- /.card -->
</div>
</div>
{% endif %}
{% if sizeProductMap_edit %}
<form action="{% url 'admin-size-product-map-edit' x.size_p_map_id %}" method="POST">
{% csrf_token %}
{{form.size_id}}
{{form.prod_id}}
</form>
{% endif %}
</div>
</div>
</div>
{% endblock %}
And if it is possible to reduce the number of line of code please also help. Thanks in advance.
I've found out the answer. There was a really a silly mistake by me.
In the sizeProductMap.html there is a mistake let me point out that:
sizeProductMap.html
{% if sizeProductMap_edit %}
<form action="{% url 'admin-size-product-map-edit' x.size_p_map_id %}" method="POST">
{% csrf_token %}
{{form.size_id}}
{{form.prod_id}}
</form>
{% endif %}
Here I am checking for instance {% if sizeProductMap_edit %} this is the wrong thing.
I have to check {% if instance %} according to my views.py.
I'm using two forms in one of my pages one for closing tickets and one for sending replies.
But problem is when I submit one of them another one is submitted too! and shows the flash massages. So I have two flash massages !
That gets more complicated since I'm checking some conditions to show first form and in that case which that form even doesn't again I have two flash massages !
#app.route('/edit-ticket', methods=['GET', 'POST'])
def edit_ticket():
if session['logged_in'] == True:
trackingNumberLink = int(request.args.get('trackingNumber'))
closeForm = CloseTicket()
editForm = EditTicket()
GetTicketStatus = tickets.find_one({"trackingNumber": trackingNumberLink})
if closeForm.validate_on_submit():
tickets.update_one({"trackingNumber": trackingNumberLink},
{"$set": {"status": "پاسخ داده شده", "order": 2}})
flash(u"تیکت مورد نظر با موفقیت بسته شد.")
if editForm.validate_on_submit():
replyDate = jdatetime.datetime.now()
tickets.update_one({"trackingNumber": trackingNumberLink},
{"$set": {"status": "در حال بررسی", "order": 1}})
tickets.update_one({"trackingNumber": trackingNumberLink},
{"$push": {"replies": {"rep": {"mass": editForm.ticketMassage.data,
"date": replyDate.strftime("%H:%M:%S %d-%m-%y "),
"HowSent": "user"}}}})
flash(u"پاسخ با موفقیت ارسال شد.")
return render_template('edit-ticket.html', Title="ویرایش تیکت", closeForm=closeForm,
editForm=editForm, CanUserCloseTicket=GetTicketStatus)
else:
return redirect(url_for('Login'))
HTML:
{% extends "layout.html" %}
{% block content_main %}
<div class="container content-box">
<div class="row">
<div class="col-sm-12">
<div class="FormSection center-form">
<fieldset class="form-group">
<legend class="border-bottom mb-4">ویرایش تیکت</legend>
</fieldset>
<form method="post" action="">
{{ editForm.hidden_tag() }}
<div class="form-group">
{{ editForm.ticketMassage.label(class="form-control-label") }}
{% if editForm.ticketMassage.errors %}
{{ editForm.ticketMassage(class="form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in editForm.ticketMassage.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ editForm.ticketMassage(class="form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ editForm.submit(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% if CanUserCloseTicket['status'] != "پاسخ داده شده" %}
<div class="FormSection center-form">
<form method="post" action="">
{{ closeForm.hidden_tag() }}
<div class="form-group">
{{ closeForm.submitCloseTicket(class="btn btn-outline-info") }}
</div>
</form>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content_main %}
Forms Class:
class EditTicket(FlaskForm):
ticketMassage = TextAreaField('متن پیام:',
description=u'پاسخ خود را بنویسید.',
validators=[data_required(), Length(min=20, max=500)], )
submit = SubmitField('ویرایش تیکت')
class CloseTicket(FlaskForm):
submitCloseTicket = SubmitField('بستن تیکت')
Render the form tag with an id attribute and for the submit and input tags use the form attribute.
<form id="edit-ticket">
{{ form.submit(form="edit-ticket") }}
The form element that the input element is associated with (its form owner). The value of the attribute must be an id of a element in the same document. If this attribute isn't used, the element is associated with its nearest ancestor element, if any. This attribute lets you to place elements anywhere within a document, not just as descendants of form elements.
Update Use different names for submit then in your views.py if close_form.validate_on_submit() and close_form.close.data:
from flask import Flask, render_template
from flask_wtf import FlaskForm, CSRFProtect
from wtforms.fields import SubmitField, TextAreaField
app = Flask(__name__)
app.config['SECRET_KEY'] = '^%huYtFd90;90jjj'
app.config['UPLOADED_FILES'] = 'static/files'
csrf = CSRFProtect(app)
class EditTicketForm(FlaskForm):
ticket_message = TextAreaField()
edit = SubmitField()
class CloseTicketForm(FlaskForm):
message = TextAreaField()
close = SubmitField()
#app.route('/edit-ticket', methods=['GET', 'POST'])
def edit_ticket():
close_form = CloseTicketForm()
edit_form = EditTicketForm()
if close_form.is_submitted() and close_form.close.data:
if close_form.validate():
x = close_form.message.data
return x.upper()
if edit_form.is_submitted() and edit_form.edit.data:
if edit_form.validate():
y = edit_form.ticket_message.data
return y.upper()
return render_template('edit-ticket.html', close_form=close_form, edit_form=edit_form)
if __name__ == "__main__":
app.run(debug=True)
edit-ticket.html
<form method="post" id="edit-form" novalidate></form>
<form method="post" id="close-form" novalidate></form>
{{ edit_form.csrf_token(form="edit-form") }}
{{ close_form.csrf_token(form="close-form") }}
{{ edit_form.ticket_message(form="edit-form") }}
{{ edit_form.edit(form="edit-form") }}
{{ close_form.message(form="close-form") }}
{{ close_form.close(form="close-form") }}
Put an action on your forms instead of leaving it blank:
<form method="post" action="/close-ticket"> ... </form>
<form method="post" action="/edit-ticket"> ... </form>
Define explicit functions to handle each action. One action, one function - keep it simple. Split out and re-use the logged-in logic for each.
#app.route('/close-ticket', methods=['POST'])
def close_ticket():
if session['logged_in'] != True:
return redirect(url_for('Login'))
# closeForm handling, etc....
#app.route('/edit-ticket', methods=['POST'])
def edit_ticket():
if session['logged_in'] != True:
return redirect(url_for('Login'))
# editForm handling, etc....
I am trying to make a voting app in django.
Here the view that display a vote.
class DetailVoteView(View):
"""
Displays the vote
If vote is active allows to vote
If vote is completed shows winners and top 5
"""
vote = None
vote_for_chars = None
page_title = ''
def dispatch(self, request, *args, **kwargs):
self.vote = Vote.objects.get(id=kwargs['id'])
self.vote_for_chars = self.vote.voteforcharacter_set.all()
self.page_title = self.vote.title
return super(DetailVoteView, self).dispatch(request, *args, **kwargs)
def get(self, request, id):
if is_active_vote(self.vote):
nominates = self.vote_for_chars
return render(request, 'vote_detail/active_vote_detail.html', context={
'page_title': self.page_title,
'vote': self.vote,
'votes_name': self.page_title,
'nominates': nominates,
})
else:
winners = []
top_fives = []
if self.vote.voteforcharacter_set.count() != 0:
sorted = self.vote.voteforcharacter_set.order_by('-votes_number')
winner_number_votes = sorted[0].votes_number
winners = self.vote_for_chars.filter(votes_number__exact=winner_number_votes)
top_fives = sorted[winners.count():5 + winners.count()]
return render(request, 'vote_detail/completed_vote_detail.html', context={
'page_title': self.page_title,
'vote': self.vote,
'votes_name': self.page_title,
'winners': winners,
'top_fives': top_fives
})
def post(self, request, id):
vote_for_chars = self.vote_for_chars
id_to_vote = request.POST.get("id_to_vote")
char_to_vote = vote_for_chars.get(character__id=id_to_vote)
char_to_vote.votes_number += 1
char_to_vote.save()
return HttpResponseRedirect('/')
The code is not DRY as I suppose. Because, there is the same context in get reuqest.
I need to use a mixins feature?
How can I improve it? Thanks.
EDITED.
Added code for templates.
acvtive_vite_detail.html
{% extends 'base/base.html' %}
{% block content %}
<form action="." method="POST">{% csrf_token %}
<p>Vote: {{ vote }}.</p>
<p>Choose:</p>
<div>
{% for item in nominates %}
{% include "base/listOutput.html" %}
<input type="radio" id="{{ item.id }}"
name="id_to_vote" value="{{ item.character.id }}" checked>
<label for="{{ item.character.name }}">{{ item.character.name }}
</label>
{% endfor %}
</div>
<div>
<button type="submit">Vote!</button>
</div>
</form>
{% endblock content %}
completed_vote_detail.html
{% extends 'base/base.html' %}
{% block content %}
<p>Vote: {{ vote }}.</p>
<p>Winners: </p>
{% for item in winners %}
<p>{% include "base/listOutput.html" %}</p>
{% endfor %}
<p>Top5: </p>
{% for item in topFives %}
<p>{% include "base/listOutput.html" %}</p>
{% endfor %}
{% endblock content %}
listOfOutput.html
<div style="border-style: solid; width: 25%">
<img src="{{ item.character.image.url }}" alt="img" class="img-responsive img-rounded" width="100%" height=auto>
<p>Name: {{ item.character.name }}</p>
<p>Age: {{ item.character.age }}</p>
<p>Votes number: {{ item.votes_number }}</p>
</div>
I have a model that describes a Webpage. The source_upload field represents a screenshot of the webpage.
For adding site-objects to my application, I use a django class-based CreateView. This works really well.
Now I'm trying to add a semi-automatic way of adding sites. You can pass an URL to the view and the view fills the form automatically (and makes a screenshot of the webpage). The user should be able to review all the auto-extracted fields - especially the auto generated screenshot image - change them and hit the save button to add the object to the database and the image (if approved) to its final location.
I tried to implement this in the get_initial method of the view. This works quite well except for the screenshot-FileField. The path I set in initial['source_upload'] is not shown in the current: <link>part of the FileInput widget of the form.
How can I give the filefield an initial value?
models.py
class Site(models.Model):
def get_source_upload_path(instance, filename):
now = datetime.datetime.now()
return "appname/sites/{}/{}/{}/site_{}_{}".format(now.year, now.month, now.day, instance.pk, filename)
creationDate = models.DateTimeField(auto_now_add=True)
last_modifiedDate = models.DateTimeField(auto_now=True)
creator = models.ForeignKey('auth.User', related_name='siteCreated')
last_modifier = models.ForeignKey('auth.User', related_name='siteLast_modified')
date = models.DateTimeField(default=datetime.date.today)
title = models.CharField(max_length=240, blank=True)
body = models.TextField(max_length=3000)
source_url = models.URLField(blank=True)
source_upload = models.FileField(upload_to=get_source_upload_path, blank=True)
keywords = models.ManyToManyField("Keyword")
urls.py
url(r'site/add/$', views.SiteCreate.as_view(), name='site-add'),
url(r'site/add/(?P<source_url>[A-Za-z0-9\-._~:/\[\]#!$&\'\(\)\*\+,;=?#]+)/$', views.SiteCreate.as_view(), name='site-add-fromurl'),
forms.py
class SiteForm(ModelForm):
class Meta:
model = Site
fields = ['date', 'title', 'body', 'source_url', 'source_upload', 'keywords']
widgets = {
'keywords' : CheckboxSelectMultiple(),
}
views.py
class SiteCreate(LoginRequiredMixin, CreateView):
model = Site
template_name = 'appname/site_form.html'
form_class = SiteForm
success_url = reverse_lazy('appname:index')
def form_valid(self, form):
form.instance.creator = self.request.user
form.instance.last_modifier = self.request.user
return super(SiteCreate, self).form_valid(form)
def get_initial(self):
# Get the initial dictionary from the superclass method
initial = super(SiteCreate, self).get_initial()
try:
#get target url from request
fullpath = self.request.get_full_path()
fullpath = fullpath.split("/")
fullpath, querystring = fullpath[3:-1], fullpath[-1]
source_domain = fullpath[2]
fullpath = "/".join(fullpath)
fullpath += querystring
source_url = fullpath
if (not source_url.startswith("http://") and not source_url.startswith("https://")):
print("ERROR: url does not start with http:// or https://")
return initial
# ...
# extract title, date & others with BeautifulSoup
# ...
#extract screenshot (is there a better way?)
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(source_url)
tmpfilename = "{}_{}.png".format(get_valid_filename(source_domain), get_valid_filename(title[:30]))
now = datetime.datetime.now()
tmpfilepath_rel = "appname/sites/tmp/{}/{}/{}/{}".format(now.year, now.month, now.day, tmpfilename)
tmpfilepath = settings.MEDIA_ROOT + tmpfilepath_rel
folder=os.path.dirname(tmpfilepath)
if not os.path.exists(folder):
os.makedirs(folder)
driver.save_screenshot(tmpfilepath)
driver.quit()
initial = initial.copy()
initial['source_url'] = source_url
initial['title'] = title
initial['date'] = soup_date
initial['body'] = body
initial['source_upload'] = tmpfilepath_rel
except KeyError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
except IndexError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
return initial
site_form.html (Used for Create and Update view)
{% extends "appname/base.html" %}
{% load staticfiles %}
{% block header %}
<link rel="stylesheet" type="text/css" href="{% static 'appname/model_forms.css' %}" />
{% endblock %}
{% block body %}
<form enctype="multipart/form-data" action="" method="post">{% csrf_token %}
<div class="fieldWrapper">
<div class="error">{{ form.date.errors }}</div>
<div class="label">{{ form.date.label_tag }}</div>
<div class="field">{{ form.date }}<br />{{ form.date.help_text }}</div>
<div class="floatclear"></div>
</div>
<div class="fieldWrapper">
<div class="error">{{ form.title.errors }}</div>
<div class="label">{{ form.title.label_tag }}</div>
<div class="field">{{ form.title }}<br />{{ form.title.help_text }}</div>
<div class="floatclear"></div>
</div>
<div class="fieldWrapper">
<div class="error">{{ form.body.errors }}</div>
<div class="label">{{ form.body.label_tag }}</div>
<div class="field">{{ form.body }}<br />{{ form.body.help_text }}</div>
<div class="floatclear"></div>
</div>
<div class="fieldWrapper">
<div class="error">{{ form.source_url.errors }}</div>
<div class="label">{{ form.source_url.label_tag }}</div>
<div class="field">{{ form.source_url }}<br />{{ form.source_url.help_text }}</div>
<div class="floatclear"></div>
</div>
<div class="fieldWrapper">
<div class="error">{{ form.source_upload.errors }}</div>
<div class="label">{{ form.source_upload.label_tag }}</div>
<div class="field">{{ form.source_upload }}<br />{{ form.source_upload.help_text }}</div>
<div class="floatclear"></div>
</div>
<div class="fieldWrapper">
<div class="error">{{ form.keywords.errors }}</div>
<div class="label">{{ form.keywords.label_tag }}</div>
<div class="field">
<ul class="checkbox-grid">
{% for kw in form.keywords %}
<li>
{{ kw.tag }}
<label for="{{ kw.id_for_label }}">
{{ kw.choice_label }}
</label>
</li>
{% endfor %}
</ul>
<div class="checkbox_help_text"><br />{{ form.keywords.help_text }}</div>
</div>
<div class="floatclear"></div>
</div>
<input type="submit" value="Save" />
</form>
<div id="ObjectHistory">
{% if site.pk %}
<p>Created by: {{ site.creator }}</p>
<p>Created on: {{ site.creationDate }}</p>
<p>Last modified by: {{ site.last_modifier }}</p>
<p>Last modified on: {{ site.last_modifiedDate }}</p>
<p>Now: {% now "Y-m-d H:i:s" %} <button>delete</button></p>
{% else %}
<p>This is a new Site!</p>
<p>Now: {% now "Y-m-d H:i:s" %}</p>
{% endif %}
</div>
{% endblock %}
This is because the value of FileField, as used by your form, isn't just the path to the file - it's an instance of FieldFile (see https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.fields.files.FieldFile).
I'm not sure if you can instantiate a FieldFile directly, but at least you can do it by instantiating the model (you don't need to save it).
In views.py:
tmp_site = Site(source_upload=tmpfilepath_rel)
initial['source_upload'] = tmp_site.source_upload
Alternatively you can manually add a link to the file when rendering the html:
<div class="currently">{{ form.source_upload.value }}</div>