I am trying to load a simple csv file into django model named as class Team
class Team(models.Model):
Team = models.CharField(max_length=255,primary_key=True)
Description = models.CharField(max_length=255)
def __str__(self):
return self.Team
Views.py
def model_form_upload(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
form = DocumentForm()
return render(request, 'core/model_form_upload.html', {
'form': form
})
HTML
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
<p>Return to home</p>
{% endblock %}
forms.py
class DocumentForm(forms.ModelForm):
class Meta:
model = Document
fields = ('description', 'document', )
I have create a simple html page to load the file into the following location MEDIA_ROOT=os.path.join(BASE_DIR,"media")
I am able to load my file into that location but I need some help with passing on the data to the actual database and load the values into the table "Team". Any suggestiond on this?
Related
I'm trying to make model based form but something went wrong.
model:
class Topic(models.Model):
name = models.CharField(max_length=200)
icon = models.ImageField(upload_to = 'images/')
form:
class TopicCreationForm(ModelForm):
class Meta:
model = Topic
fields = '__all__'
view:
def TopicCreateView(request):
form = TopicCreationForm()
if request.method == 'POST':
form = TopicCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
print('aaa') # It displays in console
context = {'form':form}
return render(request, 'blog/topic_form.html', context)
my form html part
<form method="POST">
{% csrf_token %}
<fieldset >
<legend> New Topic</legend>
{{ form|crispy }}
</fieldset>
<div>
<input type="submit" value="submit" class="button-33" role="button">
</div>
</form>
where did i make mistake ?
You need to pass both request.POST and request.FILES [Django-doc], so:
def topic_create(request):
if request.method == 'POST':
form = TopicCreationForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
print('aaa') # It display in console
else:
form = TopicCreationForm()
context = {'form':form}
return render(request, 'blog/topic_form.html', context)
In the HTML form, you need to specify that the files should be encoded with the enctype="…" attribute [mdn]:
<form method="post" enctype="multipart/form-data">
…
</form>
views.py
def post(request):
if request.method == 'POST':
form = PostModelForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
# using the for loop i am able to save the tags data.
# for tag in form.cleaned_data['tags']:
# post.tags.add(tag)
images = request.FILES.getlist('images')
for image in images:
ImagesPostModel.objects.create(post=post, images=image)
return redirect('/Blog/home/')
else:
form = PostModelForm(request.POST)
return render(request, 'post.html', {'form': form})
models.py
class PostModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_time = models.DateTimeField(auto_now_add=True)
title = models.TextField(null=True)
body = models.TextField(null=True)
tags = TaggableManager()
def __str__(self):
return str(self.user)
post.html
{% extends 'base.html' %}
{% block content %}
<form action="{% url 'post' %}" enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="file" multiple name="images">
<input type="submit">
</form>
{% endblock %}
After giving the input the data is stored in the tags field but, not saving in the database.
I can manually insert data through the admin panel successfully but not as a non-staff user.
I have installed taggit and placed it in the installed_apps in settings.py.
Tags are being saved using post.tags.add(tag) inside for loop. What is the issue with the code?
This is because you use commit=False for the form: then the form has no means to save the many-to-many fields. It is also not necessary to do that, you can work with:
def post(request):
if request.method == 'POST':
form = PostModelForm(request.POST)
if form.is_valid():
form.instance.user = request.user # set the user
post = form.save() # save the form
ImagesPostModel.objects.bulk_create([
ImagesPostModel(post=post, images=image)
for image in request.FILES.getlist('images')
])
return redirect('/Blog/home/')
else:
form = PostModelForm()
return render(request, 'post.html', {'form': form})
Note: Models normally have no Model suffix. Therefore it might be better to rename PostModel to Post.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
I have used multiple FileFields in a model and my app gives error "The submitted file is empty" on execution, folowing are the details of my code:
My models.py:
class KBCTest(models.Model):
algorithm = models.CharField(max_length=10, blank=False)
entityFile = models.FileField(blank=False,
upload_to=updateFilename,
validators=[validateTestingFileExtension])
relationFile = models.FileField(blank=False,
upload_to=updateFilename,
validators=[validateTestingFileExtension])
My forms.py
class KBCTestForm(forms.ModelForm):
class Meta:
model = KBCTest
fields = ('algorithm', 'entityFile', 'relationFile')
def clean(self):
super(KBCTestForm, self).clean()
data = self.cleaned_data
return data
My views.py:
def testing(request):
title = 'Testing'
template = 'testing.html'
form = ''
if request.method == 'GET':
form = KBCTestForm()
if request.method == 'POST':
form = KBCTestForm(request.POST, request.FILES)
if form.is_valid():
form.save()
runAlgo = Run(form.cleaned_data)
runAlgo.configAndTest()
return HttpResponseRedirect(reverse('learning', kwargs={'function': 'testing'}))
context = {'title': title, 'form': form}
return render(request, template, context)
My template:
{% if request.user.is_authenticated %}
<div class='col-sm-4 col-sm-offset-4'>
<h1>{{ title }}</h1>
<!-- If form not rendered(i.e. views context) don't show submit button -->
{% if form %}
<!-- Use 'csrf_token' to prevent cross-site forgery -->
<form enctype='multipart/form-data' method='POST', action=''>
{% csrf_token %}
{{ form|crispy }} </br>
{{ form.non_field_errors|crispy }}
<input type='submit' value='Test' class='btn btn-default'/>
</form>
{% endif %}
</div>
{% endif %}
When I run this template it fails to validate the form and gives error "The submitted file is empty" error as visible in the screenshot below:
Check out this part of the Django docs, where it mentions the parameter allow_empty_file for the forms.FileField. Maybe it gives you a few clues.
Note: I'm not exactly sure how this applies to ModelForm or Model.FileField.
I have designed a model in Django and a form according to it. The below are the both files.
models.py
from django.db import models
class TotalEvent(models.Model):
CustomerID = models.CharField(max_length=30)
eventID = models.CharField(max_length=100)
eventPlace = models.CharField(max_length=100)
eventStartTime = models.TimeField(auto_now=False)
eventDate = models.DateField(auto_now=False)
forms.py
from django import forms
from django.forms import ModelForm
from catering.models import TotalEvent
class TotalEventForm(ModelForm):
class Meta:
model = TotalEvent
fields = '__all__'
Now, When in my html file I tried this:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Detail page</h1>
<p>Enter your schedule details here</p>
<form method="post">{% csrf_token %}
{% for field in forms %}
{{field}}
<input type="submit" value="Submit"/>
{% endfor %}
</form>
{% endblock %}
views.py
from django.shortcuts import render
from catering.forms import TotalEvent
def add(request):
if request.method == 'POST':
form = TotalEvent(request.POST)
if form.is_valid():
form.save()
return render(request, 'index.html', { 'form': TotalEvent()
})
In the output it shows no input fields except the following output
Enter your schedule details here
Please have a look and let me know where is the error.
Use TotalEventForm instead TotalEvent as TotalEvent is model class not form class, update your views.py
def add(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = TotalEventForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = TotalEventForm()
return render(request, 'index.html', {'form': form})
and you can use form directly in your html file.
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit"/>
</form>
type
{% for field in form %}
instead of
{% for field in forms %}
I have a listing model and a photo model:
class Listing(models.Model):
title = models.CharField(max_length=255)
<more fields>...
class Photo(models.Model):
image = models.ImageField(upload_to=create_file_path)
listing = models.ForeignKey(Listing, related_name='photos')
I am using a CBV, UpdateView, to edit a listing. I am using this form:
class ListingDetailForm(forms.ModelForm):
class Meta:
model = Listing
exclude = []
and the inline formset in forms.py to make deleting/changing the image possible:
PhotoFormset = inlineformset_factory(Listing, Photo, fields='__all__', extra=1)
here is my view:
class ListingDetailView(UpdateView):
model = Listing
template_name = 'listing/listing_detail.html'
form_class = ListingDetailForm
success_url = '/store/'
def get_context_data(self, **kwargs):
self.object = self.get_object()
context = super(ListingDetailView, self).get_context_data(**kwargs)
if self.request.POST:
context['form'] = ListingDetailForm(self.request.POST, instance=self.object)
context['photo_form'] = PhotoFormset(self.request.POST, self.request.FILES, instance=self.object)
else:
context['form'] = ListingDetailForm(instance=self.object)
context['photo_form'] = PhotoFormset(instance=self.object)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
photo_form = PhotoFormset(self.request.POST)
print photo_form.is_valid()
if form.is_valid() and photo_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
print 'in form valid for update'
context = self.get_context_data()
base_form = context['form']
photo_form = context['photo_form']
# print base_form
# print photo_form
if base_form.is_valid() and photo_form.is_valid():
print 'forms are valid for update'
base_form.save()
photo_form.save()
return super(ListingDetailView, self).form_valid(form)
else:
return self.render_to_response(self)
and the relevant template section:
{% block body %}
<form action="" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{% for field in photo_form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }}<br><br>
{% endfor %}
{{ photo_form.management_form }}
<input type="submit" value="Update" />
</form>
{% endblock %}
The issues I am having are:
1) If there is a photo attached to the listing, through the admin, the photo form does not pass validation if I do nothing with the photo form, e.g. change only fields from the listing model. The photo form displays no errors when the page reloads after invalid.
2) selecting a new photo does not change the current photo, the photo form does not validate and displays no errors.
3) if there is currently no photo related to the listing trying to add one validates through the form but does not actually save a photo related to that listing.
Deleting an image, if there is one attached to the listing, works just fine. Deleting the image and updating some other field from the listing works. If there is no image updating only a listing field works. Adding a second photo to the listing through the form does not work and displays no form errors.
There are a few issues I noticed with your form.
You need to include enctype="multipart/form-data" on your form attributes or else you won't be able to post file data to the server
I would use the Django methods for rendering the form (form.as_p, form.as_table or form.as_ul) if you absolutely need to use manual rendering then follow the official guide: model formsets
On the post method your formset is missing FILES and instance
Once you implement these changes your formset should work just fine.