Django - Custom Model Form used in a template - django

I've been trying to figure out how to create a custom html template that when submitted will upload to a model form. I'm newer to Django so so far i've been a little confused on the Django Docs on the forms. I have created a custom HTML Template it looks like:
HTML:
<form role="form" method="post" action="." id="js-upload-form" enctype="multipart/form-data">
{% csrf_token %}
<img id="image1" src="/media/{{ gallery.logo }}" alt="">
<input type="file" name="logo" id="logo" multiple>
<br>
<input type="submit" value="Register" id="js-upload-submit" >
</form>
You can notice that I have given the input ID = logo. When I click submit I would like this to upload an image to my ModelForm.
Form:
class UploadFileForm(ModelForm):
logo = forms.ImageField(required=False)
class Meta:
model = Content
fields = ['logo']
Models:
class Content(models.Model):
logo = models.ImageField(upload_to=content_file_name, null=True, blank=True)
Is there anyway with the specific way I have designed my HTML template to submit the image to the Model Form? I am trying to avoid using { form.as_p } and such as it doesnt do the customization I would like.

You should send the form object to the template and call the {{form.logo}} field.
View:
if request.method == 'POST': # When the form is submitted
form = UploadFileForm(request.POST)
if form.is_valid():
new_content = form.save()
# After the form.save a new model is created
# and the file is uploaded to the desired location
else:
form = UploadFileForm()
ctx = {}
ctx['form'] = form
return render_to_response('yourtemplate.html', ctx, context_instance=RequestContext(request))
Template:
<form role="form" method="post" action="." id="js-upload-form" enctype="multipart/form-data">
{% csrf_token %}
{{form.logo}}
</form>
Customization:
If you would like to customize the input field, you should hide the form field like:
<form role="form" method="post" action="." id="js-upload-form" enctype="multipart/form-data">
{% csrf_token %}
{{form.logo.as_hidden}} # This won't show the input
</form>
And now to customize the input you should show your custom input and via jQuery or JavaScript bind the custom input/button to the hidden form logo field.
E.g:
If you want to trigger the file select with a custom button, you should do:
# ... Other code
<button class='btn btn-success yourclass' onClick='selectFile'>
<script>
function selectFile(){
$('#id_logo').click()
}
<script>

Related

post django form data via iframe

I have a django form that I want to display on another website via iframe. The form displays ok but whenever I try to submit the form that is displayed in the iframe, I get a "server refused to connect" error message.
Is it possible to make a django form work with iframe or is there a better way to do it?
The views code for the form:
from django.views.decorators.clickjacking import xframe_options_exempt
#xframe_options_exempt
def booking_create_view(request):
form=BookingForm
submitted = False
if request.method=='POST':
form = BookingForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/?submitted=True')
else:
form = BookingForm
if 'submitted' in request.GET:
submitted = True
return render(request, "booking_form.html",{'form':form, 'submitted': submitted})
HTML for the form:
<form class="" action="" method= POST>
<div class="form-group">
{% csrf_token %}
{{ form.as_p }}
<input type="Submit" value="Submit" class = "btn btn-secondary">
</form>
{% endif %}
The iframe:
<h1>The iframe element</h1>
<iframe src="http://127.0.0.1:8000/" title="test">
</iframe>
Note: I have also tried using a live server (pythonanywhere) that had the same result

django form populate multiple identical field form in one submit

I don't want to use django form class as they will not give me much flexibility.
I have a form where will random number field in easy request. i am trying to populate the multiple value of forms that appears.
this is my models.py
class Profile(models.Model):
name = models.CharField(max_length=100)
photo = models.FileField()
and this my form.html
<form method="POST" action="{% url 'form' %}">
{% csrf_token %}
{% for i in range %}
<input type="text" id="name" name="name"><br>
<input type="file" id="photo" name="photo"><br><br>
{% endfor %}
<input type="submit" value="Submit">
</form>
You may notice I am rendering field with for loop.
that is means, there will be as much field as possible can be appear based on user request.
So I want to populate these models.
my view looks like
def form_view(request):
if request.method == 'POST':
# Need to puplate the form
return render(request, 'form.html', {'range': range(40)})
Can anyone please help me how can i achieve this? i am just struggling to achieve this.
you can use modelformset_factory for this. this way,
in your views.py
from .models import Profile
from django.forms import modelformset_factory
def form_view(request):
form_range = 40 # set the range here
ProfileFormSet = modelformset_factory(Profile, fields=("name", "photo"), extra=form_range, max_num=form_range)
formset = ProfileFormSet(request.POST or None)
if request.method == "POST":
if formset.is_valid():
formset.save()
return render(request, "form.html", {"profile_formset": formset})
and in your form html
<form method="POST" action="{% url 'form' %}">
{% csrf_token %}
{{ profile_formset.as_p }}
<input type="submit" value="Submit">
</form>

How to change default image in Django

I have a django app that allows users to fill out a form, and attach an image if they like. If they decide not to attach an image, I want a default image in it's place. The problem is that when the user tries to attach an image during the post creation, it doesn't save. It only saves when the post is edited.
model field:
image = models.ImageField(upload_to='images/', default = 'noImageAttached.png')
This works as expected when a user creates a new post and does not add a new image. The default image 'noImageAttached.png' is used.
However, when someone wants to attach an image in theCreateView it will not throw any errors, it just will simply not save the image.
When this same post is edited with UpdateView, you can upload an image, and it works. Something in my CreateView is causing it to not work? Or maybe there is a different way of using default in models.py?
views.py
class assetCreateView(LoginRequiredMixin,CreateView):
model = Assets
form_class = Asset_Creation_Form
template_name = 'addAsset.html'
login_url = 'login'
success_url = reverse_lazy('home')
#these fields are hidden from user, and filled out automatically
def form_valid(self, form):
form.instance.createdBy = (self.request.user.first_name)+ " "+ (self.request.user.last_name)
return super().form_valid(form)
forms.py
class Asset_Creation_Form(ModelForm):
class Meta:
model = Assets
fields = ('assetMake', 'assetModel', 'assetDescription', 'assetSerialNo',
'assetDescription','programID','programOwner','category','condition',
'location','dateAquired','purchasePrice','image','createdBy',)
addAsset.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block body %}
<h1>Add New Asset</h1>
<form action="" method="post">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success ml-2" type="submit">Save</button>
</form>
{% endblock %}
add enctype="multipart/form-data" inside your form tag.
For eg.
<form action="" method="post" enctype="multipart/form-data">

How to bookmark a page in Django?

I am trying to edit an html page so a logged in user can favorite / bookmark a video.id
Here is the .html file
<td>
<form method='POST' action="{% url 'researcher_view_app:favourite_post' video.id %}">
{% csrf_token %}
<input type='hidden' name='video' value={{ video.id }}>
<button type='submit'>Bookmark</button>
</form>
</td>
Here is the urls.py file
path('<int:fav_id>/favourite_post', views.favourite_post, name='favourite_post'),
Here is the view.py file
def favourite_post(request, fav_id):
video = get_object_or_404(Video, id=fav_id)
if request.method == 'POST':
video.
return render(request, 'researcher_view_app/%s' % fav_id)
First you modify the models.py that has the user models
class ProjectUser(AbstractUser):
images = models.ManyToManyField(Images)
def __str__(self):
return self.email
In the .html file add the following:
{% for image in available_images %}
/* show image */
<form method='post' action="{% url 'user-image-add' %}">
{% csrf_token %}
<input type='hidden' name='image' value={{image.id}}>
<button type='submit'>bookmark</button>
</form>
{% endfor %}
In your views.py add the following method
def user_image_add(request):
user_image_form = ImageForm(request.POST or None)
if request.method == 'POST' and user_image_form.is_valid():
request.user.images.add(user_image_form.cleaned_data['image'])
return JsonResponse(status=200)
raise Http404()
Create a forms.py file in your add and add the following:
class ImageForm(forms.Form):
image = forms.ModelChoiceField(queryset=Images.objects.all())
To show those bookmarked images you can just iterate over request.user.images (it gives you a QS of Images) similar to code above.
In the urls.py add the following:
path('user-image-add/', views.user_image_add, 'user-image-add')
In models.py add a method in User model for getting bool if video is bookmarked
def is_bookmarked(self, video_id):
return self.bookmarked_videos.filter(id=video_id).exists()
simirlarly is_bookmarked can be added to Video model accepting user_id and checking video.projectuser_set.
And add the following to your .html file where users bookmarked a video
`{% if video.is_bookmarked %}`
Delete the UserProfile as you do not need it. Just make sure to have needed instance in context of view.

Django Model Form Image Field Does Not Validate

I am writing a simple view using Django Model Form, however image field fails to validate with 'This field is required' error message.
I wonder where the problem is...
Model:
class Deal(AbstractModel):
IMAGE_MAX_LENGTH = 200
place = models.ForeignKey(Place, related_name='deals', related_query_name='deal', verbose_name=_("Place"))
image = models.ImageField(default='deals/default.png', max_length=IMAGE_MAX_LENGTH, upload_to='deals', verbose_name=_("Image"))
...
View:
#login_required
def deals_create(request):
# Get place id
place_id = request.GET.get('place')
# Get place
place = Place.objects.get(id=place_id)
# Process form data
if request.method == 'POST':
form = DealsCreateForm(request.POST, request.FILES)
# Validate post data
if form.is_valid():
# Save deal data
deal = form.save(commit=False)
deal.place = place
deal.save()
# Redirect to reload page and clear post data
return HttpResponseRedirect(reverse('deal_manager:deals_pending'))
else:
form = DealsCreateForm()
return render(request, 'deal_manager/deals_create.html', {
'form': form,
'place': place,
})
Form:
class DealsCreateForm(ModelForm):
class Meta:
model = Deal
fields = [
'image', 'product_name', 'product_description',
'regular_price', 'sale_price', 'limit', 'terms',
]
Template:
{% extends "deal_manager/deal_manager.html" %}
{% load i18n %}
{% load staticfiles %}
{% block page_content_body %}
<div class="row">
<div class="span12">
<form action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{% trans 'Create' %}" />
</form>
</div>
</div>
<div class="gap gap-small"></div>
{% endblock page_content_body %}
Note: Form validates when I remove the image field from form meta fields.
Note: File uploads works fine with Django Admin for this model.
You'll need to include enctype="multipart/form-data" in order to bind imagefield and filefield data to the form. Without that, those fields won't validate.
{% block page_content_body %}
<div class="row">
<div class="span12">
<form enctype="multipart/form-data" action="{% url 'deal_manager:deals_create' %}?place={{ place.id }}" method="post">
...
Here's the relevant documentation: https://docs.djangoproject.com/en/stable/ref/forms/api/#binding-uploaded-files-to-a-form