Why for loop only save the last file in Django? - django

When I choose two images in my template, the save method always save the last image selected but I don't understand what it is happens.
this is my view:
class imgcreate(CreateView):
model = Archivos
template_name = 'img.html'
form_class = imgForm
success_url = reverse_lazy('BackEnd:unidades')
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('imagen')
if form.is_valid():
a = 0
for imagen in files:
a = a+1
img = form.save(commit=False)
img.id_unidad = 1
img.tipo_archivo = 1
img.nombre_archivo ='hhh'+ str(a)
img.save()
print(a);
return self.form_valid(form)
else:
return self.form_invalid(form)
print always returns the name of the image with 2 that mean only the last image is saved

This works for me:
if request.method=="POST":
form = PlanfileForm(request.POST, request.FILES)
if form.is_valid():
files = request.FILES.getlist('large_img')
for a_file in files:
instance = Planfile(
plan_id = 1, #the foreign key
large_img=a_file
)
instance.save()
return HttpResponse("success!")
else:
...

Related

prepoluate a generec createview

i want that a form is prepoluate with data
my model:
TYPE = (("S",'Swing'),
("R","Rapide"))
class valuation(models.Model):
stock = models.ForeignKey("stock",on_delete=models.CASCADE,related_name='valuation',)
date = models.DateField(auto_created=True)
val_type = models.CharField(choices=TYPE, max_length=1,default='R')
user = models.ForeignKey("users.User", on_delete=models.CASCADE)
def __str__(self):
return f"{self.stock} - {self.date} - {self.val_type}"
my view:
class valuationCreateviewSwing(CreateView):
template_name = "evaluation/evaluation_create.html"
form_class = valuationModeform
def get_form_kwargs(self): # prepopulate form
kwargs = super(valuationCreateviewSwing, self).get_form_kwargs()
stck = get_object_or_404(stock, pk=self.kwargs['pk'])
kwargs['user'] = self.request.user
kwargs['val_type'] = "S"
kwargs['stock'] = stck
return kwargs
def get_context_data(self, **kwargs):
# we need to overwrite get_context_data
# to make sure that our formset is rendered
data = super().get_context_data(**kwargs)
if self.request.POST:
data["val_detail"] = ChildFormset1(self.request.POST)
else:
data["val_detail"] = ChildFormset1()
data.update({
"typeVal": "Swing",})
return data
def form_valid(self, form):
context = self.get_context_data()
val_detail_Swing = context["val_detail_Swing"]
self.object = form.save(commit=False)
# add data info neede about valuation model
self.object = form.save()
if val_detail_Swing.is_valid():
val_detail_Swing.instance = self.object
val_detail_Swing.save()
return super().form_valid(form)
def get_success_url(self):
return reverse("stock:stock-list")
I've a child form in my view (this part works ok):
ChildFormset1 = inlineformset_factory(
valuation, val_detail_Swing, form=valuationSwingModelform, can_delete=False)
I tried to use ge_for_kwargs but it seems not working as I've an error message :
init() got an unexpected keyword argument 'user'
You can use get_initial() method:
class valuationCreateviewSwing(CreateView):
template_name = "evaluation/evaluation_create.html"
form_class = valuationModeform
def get_initial(self):
query = self.request.GET
return {
'user': self.request.user.pk
'val_type': "S",
'stock': self.kwargs.get('pk')
}
...
Or you should override __init__() method and stay to use get_form_kwargs()
class valuationModeform(ModelForm):
class Meta:
model = Valuation
fields = '__all__'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
val_type = kwargs('val_type', None)
stock = kwargs.pop('stock', None)
super().__init__(*args, **kwargs)
# assign initial values
self.fields['user'].initial = user
self.fields['val_type'].initial = val_type
self.fields['stock'].initial = stock

form for formset object has no attribute 'cleaned deta'

I have genericview which handle 3 difference form(2 formsets), when i try check cleaned_data, i have error, but when i try make the same by debugger i didn't see anything problem, who may know why i can't make it?
My View :
class CompanyCreateView(LoginRequiredMixin, CreateView):
model = Company
template_name = 'main/company/create_page.html'
form_class = CompanyCreateForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['page'] = Page.objects.active().filter(slug='add_company').first()
if self.request.POST:
context['images'] = ImageGalleryFormSet(self.request.POST, self.request.FILES)
context['company_locations'] = CompanyLocationFormset(self.request.POST)
else:
context['images'] = ImageGalleryFormSet(self.request.GET or None)
context['company_locations'] = CompanyLocationFormset(self.request.GET or None)
return context
#transaction.atomic
def form_valid(self, form):
context = self.get_context_data()
images = context['images']
company_locations = context['company_locations']
self.object = form.save()
self.object.active = False
self.object.status = CompanyConstants.CompanyStatus.NEW
self.object.owner = self.request.user
self.object.save()
for image in range(len(images)):
key_image = 'gallery_items-' + str(image) + '-image'
form_image = self.request.FILES.get(key_image)
if form_image:
ImageGallery(image=form_image, company_id=int(self.object.id)).save()
print(company_locations.forms[0].get_cleaned_data)
for location in range(len(company_locations)):
key_locations = 'form-' + str(location) + '-location'
key_address = 'form-' + str(location) + '-address'
if self.request.POST.get(key_locations):
location = self.request.POST.get(key_locations)
address = self.request.POST.get(key_address)
company = self.object
CompanyLocation.objects.create(location=clean_location(location), address=address, company=company)
return super().form_valid(form)
def get_success_url(self):
return reverse('main:profile', args=[self.request.user.username])
When i try print this i have error, this code that i have works correct but, he is bad.
MY FORM :
class CompanyLocationForm(forms.ModelForm):
location = geo_forms.PointField(widget=GooglePointFieldWidget)
class Meta:
model = CompanyLocation
fields = ('location', 'address')
CompanyLocationFormset = formset_factory(CompanyLocationForm, max_num=10)
you need to clean your data to check the problem
#transaction.atomic
def form_valid(self, form):
def clean(self):
all_clean_data = super().clean()
all_clean_data[['page'] = Page.objects.active().filter(slug='add_company').first()
...
So i see a lot off data Just test
def Test(request):
if request.method == "POST":
form =CompanyLocationForm(data=request.POST)
if form.is_valid():
print(company_locations.forms[0].get_cleaned_data)

Validating a formset using data from another form

I'm having to do some validation across both a form and formset. The £££ amount in the form must equal the sum of the amounts in the formset.
After a lot of Googling I found a solution where I add a custom init to the baseformset as follows:
class BaseSplitPaymentLineItemFormSet(BaseFormSet):
def __init__(self, cr=None, *args, **kwargs):
self._cr = cr
super().__init__(*args, **kwargs)
def clean(self):
if any(self.errors):
return
sum_dr = 0
for form in self.forms:
sum_dr += form.cleaned_data.get('dr')
if sum_dr != float(self._cr):
raise forms.ValidationError('The amount entered needs to equal the sum of the split payments.')
I then pass the amount value from the form when the formset is instantiated, so that the value can be used in the formset validation:
lineitem_formset = LineItemFormSet(form.data['amount'], request.POST)
This worked great for the create_new view which uses formset_factory(). This morning I wrote the update view using inline_formsetfactory(), but I now get an error:
__init__() got an unexpected keyword argument 'instance'
I only have a basic understanding of how the custom init works, so I can't find a solution to this error.
Forms.py:
class SplitPaymentForm(forms.Form):
date = forms.DateField(widget=DateTypeInput())
account = GroupedModelChoiceField(queryset=Ledger.objects.filter(coa_sub_group__type='a').order_by('coa_sub_group__name','name'), choices_groupby = 'coa_sub_group')
store = forms.CharField(required=True)
amount = forms.DecimalField(decimal_places=2)
class SplitPaymentLineItemForm(ModelForm):
ledger = GroupedModelChoiceField(queryset=Ledger.objects.all().order_by('coa_sub_group__name', 'name'), choices_groupby = 'coa_sub_group', empty_label="Ledger", required=True)
project = forms.ModelChoiceField(queryset=Project.objects.filter(status=0), empty_label="Project", required=False)
class Meta:
model = LineItem
fields = ['description','project', 'ledger','dr',]
# This init disallows empty formsets
def __init__(self, *arg, **kwarg):
super(SplitPaymentLineItemForm, self).__init__(*arg, **kwarg)
self.empty_permitted = False
class BaseSplitPaymentLineItemFormSet(BaseFormSet):
def __init__(self, cr=None, *args, **kwargs):
self._cr = cr
super().__init__(*args, **kwargs)
def clean(self):
if any(self.errors):
return
sum_dr = 0
for form in self.forms:
sum_dr += form.cleaned_data.get('dr')
if sum_dr != float(self._cr):
raise forms.ValidationError('The amount entered needs to equal the sum of the split payments.')
Views.py:
def split_payments_new(request):
LineItemFormSet = formset_factory(SplitPaymentLineItemForm, formset=BaseSplitPaymentLineItemFormSet, extra=2)
if request.method == 'POST':
form = SplitPaymentForm(request.POST)
lineitem_formset = LineItemFormSet(form.data['amount'], request.POST)
if form.is_valid() and lineitem_formset.is_valid():
q0 = JournalEntry(user=request.user, date=form.cleaned_data['date'], type="SP",)
q1 = LineItem(journal_entry=q0, description=form.cleaned_data['store'], ledger=form.cleaned_data['account'], cr=form.cleaned_data['amount'])
q0.save()
q1.save()
for lineitem in lineitem_formset:
q2 = LineItem(journal_entry=q0,description=lineitem.cleaned_data.get('description'),ledger=lineitem.cleaned_data.get('ledger'),project=lineitem.cleaned_data.get('project'),dr=lineitem.cleaned_data.get('dr'))
q2.save()
messages.success(request, "Split payment successfully created.")
return HttpResponseRedirect(reverse('journal:split_payments_show_detail', kwargs={'pk': q0.id}) )
else:
form = SplitPaymentForm(initial = {'date': datetime.date.today().strftime('%Y-%m-%d')})
lineitem_formset = LineItemFormSet()
return render(request, 'journal/split_payments_new.html', {'form': form, 'formset': lineitem_formset})
def split_payments_update(request, pk):
journal_entry = get_object_or_404(JournalEntry, pk=pk, type="SP")
lineitem = LineItem.objects.get(journal_entry=journal_entry.id, dr__isnull=True)
initial = {
'date': journal_entry.date.strftime('%Y-%m-%d'),
'account': lineitem.ledger,
'store': lineitem.description,
'amount': lineitem.cr,
}
form = SplitPaymentForm(initial=initial)
LineItemFormSet = inlineformset_factory(JournalEntry, LineItem, form=SplitPaymentLineItemForm, formset=BaseSplitPaymentLineItemFormSet, extra=0)
lineitem_formset = LineItemFormSet(instance=journal_entry)
if request.method == 'POST':
lineitem_formset = LineItemFormSet(form.data['amount'], request.POST, instance=journal_entry)
form = SplitPaymentForm(request.POST)
if lineitem_formset.is_valid() and form.is_valid():
lineitem_formset.save()
journal_entry.date = form.cleaned_data['date']
lineitem.ledger = form.cleaned_data['account']
lineitem.description = form.cleaned_data['store']
lineitem.cr = form.cleaned_data['amount']
journal_entry.save()
lineitem.save()
messages.success(request, "Split payment successfully updated.")
return HttpResponseRedirect(reverse('journal:split_payments_show_detail', kwargs={'pk': journal_entry.id}) )
return render(request, 'journal/split_payments_update.html',{'form': form, 'formset': lineitem_formset, 'journal_entry': journal_entry})
Solved. Just had to use BaseInlineFormSet.

Django form with filefield loses the file when editing an instance

I'm trying to make a form that can be used to make a new instance of "LearningObjects" as well as edit existing instances. It seems to work fine except that when I'm editing an existing instance I lose the filefield. Since it is a required field it asks me to upload a new file and obviously I don't always want to do that.
Form.py
class LearningObjectuploadform(forms.ModelForm, edit):
level = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple,queryset=None,required=False)
agebracket =forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple,queryset=None,required=False)
pathway = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple,queryset=None,required=False)
class Meta:
model = LearningObject
fields =['title','archivefile','description','tags','pathway','level','subject','agebracket']
def __init__(self, *args, **kwargs):
super(LearningObjectuploadform, self).__init__(*args, **kwargs)
self.fields['level'].queryset = AssoeLevel.objects.all()
self.fields['pathway'].queryset = AssoePathway.objects.all()
self.fields['agebracket'].queryset = AgeBracket.objects.all()
View.py
def createLearningobject(request,learningobject_pk=False):
if request.method == 'GET':
if learningobject_pk:
print learningobject_pk
instance = LearningObject.objects.get( pk=learningobject_pk)
print instance
form = LearningObjectuploadform(request.POST or None, request.FILES or None, instance=instance)
else:
form = LearningObjectuploadform()
else:
form = LearningObjectuploadform(request.POST, request.FILES)
if form.is_valid():
learningobject = request.FILES['archivefile']
title = form.cleaned_data['title']
description = form.cleaned_data['description']
tags = form.cleaned_data['tags']
levels = form.cleaned_data['level']
pathways = form.cleaned_data['pathway']
agebrackets = form.cleaned_data['agebracket']
post = LearningObject.objects.create(archivefile=learningobject,title=title, description=description)
for tag in tags:
post.tags.add(tag)
for level in levels:
post.level.add(level.pk)
for pathway in pathways:
post.pathway.add(pathway.pk)
for agebracket in agebrackets:
post.agebracket.add(agebracket.pk)
post.save()
return HttpResponseRedirect(reverse('index', ))
else:
print "form not valid"
return render(request, 'mediamanager/edit_learningobject.html', {'form': form,})
Models.py
class DefaultResource(models.Model):
#
# This class is the parent class for all resources in the media manager
#
title = models.CharField(max_length=100)
created_date = models.DateTimeField(auto_now_add=True, auto_now=False)
edited_date = models.DateTimeField(auto_now_add=False,auto_now=True)
level = models.ManyToManyField(AssoeLevel)
agebracket= models.ManyToManyField(AgeBracket)
pathway= models.ManyToManyField(AssoePathway)
tags = TaggableManager()
slug = models.SlugField(max_length=100,editable=False,blank=True)
updownvotes = RatingField(can_change_vote=True)
views = models.DecimalField(max_digits=20,decimal_places=2,default=0,blank=True)
score = models.DecimalField(max_digits=20,decimal_places=4,default=0,blank=True)
icon = models.CharField(max_length=254,editable=False,blank=True)
subject = models.ManyToManyField(AssoeSubjects)
#def return_tags(self):
# taglist = self.tags.names()
# return taglist
def calculate_score(self):
score = float(self.updownvotes.likes) - float(self.updownvotes.dislikes)
score = score + (float(self.views)**(float(1)/float(2)))
self.score = score
rounded_score = int(round(self.score))
if rounded_score < -1:
return -1
else:
return rounded_score
def __unicode__ (self):
return self.title
def save(self, *args, **kwargs):
self.calculate_score()
if not self.id:
self.slug = slugify(self.title)
super(DefaultResource, self).save(*args, **kwargs)
class LearningObject(DefaultResource):
archivefile = models.FileField(upload_to='static/learningobject/archivefiles/%Y/%m/%d')
indexpath = models.CharField(max_length=254,editable=False,blank=True)
description = models.TextField(blank=True)
def unpackarchive(self):
archive = self.archivefile
filename = os.path.basename(str(archive))
folder = str(filename).split(".")[0]
print folder
index_found = "False"
with zipfile.ZipFile(archive,"r") as z:
for each in z.namelist():
if each == "index.html" or each == "index.htm":
index_found = "True"
else:
pass
if not index_found:
print "zip file does not contain a valid index.html file"
else:
path = os.path.join("static","learningobject","unpackedarchives",folder)
z.extractall(path)
self.findindex(path)
def findindex(self,path):
print path
for root, dirnames, filenames in os.walk(path):
for filename in fnmatch.filter(filenames, 'index.ht*'):
print filename
self.indexpath = os.path.join(root, filename)
print self.indexpath
def save(self, *args, **kwargs):
self.icon = "/static/images/icons/box.png"
self.unpackarchive()
super(LearningObject, self).save(*args, **kwargs)
I have faced similar problems with file uploads in django forms. This is what I hope should help you out(provided you are willing to alter the required attribute of the archivefile field.)
if request.method == 'GET':
if learningobject_pk:
print learningobject_pk
instance = LearningObject.objects.get( pk=learningobject_pk)
print instance
form = LearningObjectuploadform(request.POST or None, request.FILES or None, instance=instance)
form.base_fields['archivefile'].required = False
else:
form = LearningObjectuploadform()

how we save form through Class Based Generic View in django

i am using class based generic view in my Subject_En roll application
my view.py is
cc = 0
#login_required
def add_subject_enroll(request):
user = request.user
obj = StudentRegistration.objects.get(user=user)
print "obj.first_name",obj.first_name
first_name = obj.first_name
print "first_name",first_name
if obj.user:
print "object exist"
#form = Subject_EnrollForm(request.POST or None, initial={'student_name' : first_name})
#form = Subject_EnrollForm( initial={'student_name' : obj.first_name})
form = Subject_EnrollForm(request.POST or None, request.FILES or None)
form.fields["student_name"].initial = first_name
form.fields["birth_place"].initial = obj.birth_place
form.fields["gender"].initial = obj.gender
form.fields["phone"].initial = obj.phone
form.fields["email"].initial = obj.email
form.fields["phone"].initial = obj.phone
form.fields["nationality"].initial = obj.nationality
form.fields["religion"].initial = obj.religion
form.fields["blood_group"].initial = obj.blood_group
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
form.fields["nationality"].initial = obj.nationality
else:
print "object not found"
Subject_EnrollForm(request.POST or None, request.FILES or None)
if request.POST:
if form.is_valid():
a = form.save()
a.user = request.user
a.save()
#user.save()
messages.add_message(request,messages.SUCCESS, "your Profile was added")
#return HttpResponseRedirect('/app/all')
return HttpResponseRedirect('/')
args = {}
args.update(csrf(request))
args['form'] = form
context = RequestContext(request,
{'request': request,
'user': request.user,
'form': form})
return render_to_response('subject_enroll/add_subject_enroll.html', args, context)
class Subject_EnrollListView(ListView):
"""View to display all published and visible news entries."""
template_name = "subject_enroll/subject_enroll_list.html"
def get_queryset(self):
return Subject_Enroll.objects.all()
class DetailViewMixin(object):
"""Mixin to handle different DetailView variations."""
model = Subject_Enroll
#slug_field = 'translations__slug'
def get_queryset(self):
#return Subject_Enroll.objects.all()
return Subject_Enroll.objects.lang(self.request, False)
class Subject_EnrollDetailView(DetailViewMixin, DetailView):
def get_context_data(self, **kwargs):
context = super(Subject_EnrollDetailView, self).get_context_data(**kwargs)
context['subject_enrolls'] = Subject_Enroll.objects.all()
return context
class Subject_EnrollUpdateView(UpdateView):
form_class = Subject_EnrollForm
model = Subject_Enroll
template_name = 'subject_enroll/subject_enroll_detail.html'
def get(self, request, **kwargs):
self.object = Subject_Enroll.objects.get(id=self.request.id)
form_class = self.get_form_class()
form = self.get_form(form_class)
context = self.get_context_data(object=self.object, form=form)
return self.render_to_response(context)
def get_object(self, queryset=None):
obj = Subject_Enroll.objects.get(id=self.kwargs['id'])
return obj
i try with pass form in context of Detilviewmixin
class DetailViewMixin(object):
"""Mixin to handle different DetailView variations."""
model = Subject_Enroll
#slug_field = 'translations__slug'
def get_context_data(self, **kwargs):
context = super(DetailViewMixin, self).get_context_data(**kwargs)
#context['form'] = Subject_EnrollForm
#context['form'] = Subject_EnrollForm()
return context
def get_queryset(self):
#return Subject_Enroll.objects.all()
return Subject_Enroll.objects.lang(self.request, False)
in that form are render on template but when i press save button so it can't save record
from this code i get all field access in "subject_enroll/subject_enroll_detail.html" like {{ object.student_name }}
{{ object.enroll_status }}
so it gives value of that field but now i want to edit record in subject_enroll_detail.html template like s
subject_enroll values "draft" to "submit" with click on some buttons in subject_enroll_detail.html template
i tried with form view and updateview but can't find solution
pls help!!!
Thanks in advance!!
from django.views.generic import UpdateView
class StudentRegistrationUpdateView(UpdateView):
model = StudentRegistration
form_class = Subject_EnrollForm #don't need if you are editing all the fields
template_name = 'subject_enroll/add_subject_enroll.html'
https://docs.djangoproject.com/en/1.7/ref/class-based-views/generic-editing/#updateview
in your urls.py
import StudentRegistrationUpdateView
in urls.py don't forget to include 'pk' like below, this determines which object to be updated
url(r'student/(?P<pk>\d+)/update/$', StudentRegistrationUpdateView.as_view(), name='student_registration_update'),