Display form if its value exists in db - python

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

How can I retrieve a single value from a queryset?

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 want to edit SizeProductMapping model using Django forms but The form is not rendering - Django

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.

Flask - Submit button submits all forms instead of one form

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....

Django. DRY. Same context in get request

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>

Initially populate FileField in Django-Form

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>

Categories

Resources