prepoluate a generec createview - django

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

Related

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)

How to query through a Foreign key field inside django inline forms?

I have these models:
class Purchase(models.Model):
company = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True)
party_ac = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='partyledger')
purchase = models.ForeignKey(Ledger1,on_delete=models.CASCADE,related_name='purchaseledger')
total = models.DecimalField(max_digits=10,decimal_places=2,null=True,blank=True)
class Stock_total(models.Model):
company = models.ForeignKey(Company,on_delete=models.CASCADE,null=True,blank=True)
purchases = models.ForeignKey(Purchase,on_delete=models.CASCADE,null=True,blank=False,related_name='purchasetotal')
stockitem = models.ForeignKey(Stockdata,on_delete=models.CASCADE,null=True,blank=True,related_name='purchasestock')
total = models.DecimalField(max_digits=10,decimal_places=2,default=0.00,null=True,blank=True)
This are my forms:
class Purchase_form(forms.ModelForm):
class Meta:
model = Purchase
fields = ('Company','Party_ac', 'purchase', 'sub_total')
def __init__(self, *args, **kwargs):
self.User = kwargs.pop('User', None)
self.Company = kwargs.pop('Company', None)
super(Purchase_form, self).__init__(*args, **kwargs)
self.fields['party_ac'].queryset = Ledger1.objects.filter(Q(Company = self.Company) , Q(group1_Name__group_Name__icontains='Sundry Creditors') | Q(group1_Name__group_Name__icontains='Bank Accounts') | Q(group1_Name__group_Name__icontains='Cash-in-hand') | Q(group1_Name__Master__group_Name__icontains='Sundry Creditors') | Q(group1_Name__Master__group_Name__icontains='Bank Accounts') | Q(group1_Name__Master__group_Name__icontains='Cash-in-hand'))
self.fields['party_ac'].widget.attrs = {'class': 'select2_demo_2 form-control',}
self.fields['purchase'].queryset = Ledger1.objects.filter(Q(Company = self.Company) ,Q(group1_Name__group_Name__icontains='Purchase Accounts') | Q(group1_Name__Master__group_Name__icontains='Purchase Accounts'))
self.fields['purchase'].widget.attrs = {'class': 'select2_demo_2 form-control',}
self.fields['total'].widget.attrs = {'class': 'form-control',}
class Stock_Totalform(forms.ModelForm):
class Meta:
model = Stock_Total
fields = ('stockitem', 'Total_p')
def __init__(self, *args, **kwargs):
super(Stock_Totalform, self).__init__(*args, **kwargs)
self.fields['stockitem'].widget.attrs = {'class': 'select2_demo_2 form-control',}
self.fields['total'].widget.attrs = {'class': 'form-control',}
Purchase_formSet = inlineformset_factory(Purchase, Stock_Total,
form=Stock_Totalform, extra=3)
The views:
class Purchase_createview(ProductExistsRequiredMixin,Company_only_accounts_mixins,LoginRequiredMixin,CreateView):
form_class = Purchase_form
template_name = 'stockkeeping/purchase/purchase_form.html'
def get_context_data(self, **kwargs):
context = super(Purchase_createview, self).get_context_data(**kwargs)
company_details = get_object_or_404(Company, pk=self.kwargs['pk'])
context['company_details'] = company_details
selectdatefield_details = get_object_or_404(Selectdatefield, pk=self.kwargs['pk3'])
context['selectdatefield_details'] = selectdatefield_details
if self.request.POST:
context['stocks'] = Purchase_formSet(self.request.POST)
else:
context['stocks'] = Purchase_formSet()
return context
def form_valid(self, form):
c = Company.objects.get(pk=self.kwargs['pk'])
form.instance.Company = c
context = self.get_context_data()
stocks = context['stocks']
with transaction.atomic():
self.object = form.save()
if stocks.is_valid():
stocks.instance = self.object
stocks.save()
return super(Purchase_createview, self).form_valid(form)
def get_form_kwargs(self):
data = super(Purchase_createview, self).get_form_kwargs()
data.update(
Company=Company.objects.get(pk=self.kwargs['pk'])
)
return data
I want to perform a queryset method for stockitem field in Stock_Totalform which I will make specific to Company like I have done for Party_ac and purchase in Purchase_form above..
When I try to do the same for Stock_Totalform objects it gives me no result..
I tried like above doing: self.Company = kwargs.pop('Company', None) using the get_form_kwargs function in views.
But it looks like it doesnot works for the ForeignKey field which is inlined with a parent model.
Can anyone help to to solve this issue.
Thank you

Comparing date field in a form with current date

I am trying to check with an if statement if the date entered in a form is before the current date. If so write to an object in the model. I am also not sure if there are a better way of doing this.
I get this error
'<' not supported between instances of 'DateField' and 'datetime.date'
My view:
class ActionCreateView(LoginRequiredMixin, generic.CreateView):
login_url = '/scrty/login/'
template_name = "nodiso/actioncreate.html"
form_class = forms.LeadActionCreateForm
# success_url = reverse_lazy('nodisoapp:leaddetail', kwargs['pk'] )
def get_success_url(self, **kwargs):
return reverse("nodisoapp:leaddetail", kwargs={'pk':
self.kwargs['pk']})
def form_valid(self, form):
if form.fields['Duedate'] < datetime.date.today():
self.object.overdue = 1
else:
pass
self.object = form.save(commit=False)
self.object.lead_id = self.kwargs['pk']
self.object.creator = self.request.user.firstname
self.object.save()
return super(ActionCreateView, self).form_valid(form)
The Model:
class LeadActions(models.Model):
lead = models.ForeignKey(Leads)
name = models.CharField(max_length=265)
crdate = models.DateField(auto_now_add=True)
Duedate = models.DateField()
creator = models.CharField(max_length=265)
overdue = models.IntegerField(null=True,blank=True)
def __str__(self):
return self.name
The form:
class LeadActionCreateForm(forms.ModelForm):
class Meta:
model = models.LeadActions
fields = ['name','Duedate']
Since you already pull out the unsaved model from the form here:
self.object = form.save(commit=False)
Why not read the Duedate directly from the model instance, and set the overdue flag accordingly ?
is_overdue = self.object.Duedate > datetime.date.today()
self.object.overdue = 1 if is_overdue else None
Complete code:
class ActionCreateView(LoginRequiredMixin, generic.CreateView):
login_url = '/scrty/login/'
template_name = "nodiso/actioncreate.html"
form_class = forms.LeadActionCreateForm
# success_url = reverse_lazy('nodisoapp:leaddetail', kwargs['pk'] )
def get_success_url(self, **kwargs):
return reverse("nodisoapp:leaddetail", kwargs={'pk': self.kwargs['pk']})
def form_valid(self, form):
self.object = form.save(commit=False)
is_overdue = self.object.Duedate > datetime.date.today()
self.object.overdue = 1 if is_overdue else None
self.object.lead_id = self.kwargs['pk']
self.object.creator = self.request.user.firstname
self.object.save()
return super(ActionCreateView, self).form_valid(form)

IntegrityError with a foreignKey

i have these models, states and cities,
class State(models.Model):
name = models.CharField(max_length=255)
shortname = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class City(models.Model):
name = models.CharField(max_length=255)
state = models.ForeignKey(State)
def __unicode__(self):
return self.name
and im getting a "IntegrityError (1048, "Column 'state_id' cannot be null")" when i save the form, the weird thing is that the state are created, this is what im doing
def form_valid(self, form):
city = form.cleaned_data['city_name']
state = form.cleaned_data['state_name']
m = State.objects.get_or_create(name=state)
state_id = m[0].id
City.objects.get_or_create(name=state, id=state_id)
form.save()
what can i do?
class StoreForm(ModelForm):
class Meta:
model = Store
fields = '__all__'
class StoreGoogleMapForm(StoreForm):
city_name = forms.CharField(
widget=forms.TextInput(
attrs={'readonly': 'readonly'}
)
)
state_name = forms.CharField(
widget=forms.TextInput(
attrs={'readonly': 'readonly'}
)
)
class Meta(StoreForm.Meta):
exclude = (
'state', 'city'
)
widgets = {
'retailer': forms.HiddenInput(),
'lon': forms.HiddenInput(),
'lat': forms.HiddenInput(),
}
def clean(self):
cleaned_data = super(StoreGoogleMapForm, self).clean()
city_name = cleaned_data.get("city_name")
state_name = cleaned_data.get("state_name")
return cleaned_data
class NewStore(LoginRequiredMixin, CreateView):
model = Store
template_name = "new_store.html"
form_class = StoreGoogleMapForm
def get_context_data(self, **kwargs):
ctx = super(NewStore, self).get_context_data(**kwargs)
ctx['cobrand'] = self.retailer
return ctx
def get(self, request, *args, **kwargs):
self.retailer = get_object_or_404(Cobrand, pk=kwargs['pk'])
self.object = Store(retailer=self.retailer)
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.render_to_response(self.get_context_data(form=form))
def form_valid(self, form):
city = form.cleaned_data['city_name']
state = form.cleaned_data['state_name']
m = State.objects.get_or_create(name=state)
City.objects.get_or_create(name=city, state=m[0])
form.save()
messages.add_message(
self.request,
messages.SUCCESS,
'The store was successfuly created!',
extra_tags='success'
)
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return reverse_lazy('store_list', kwargs={'pk': self.kwargs['pk']})
def post(self, request, *args, **kwargs):
self.retailer = get_object_or_404(Cobrand, pk=kwargs['pk'])
self.object = Store(retailer=self.retailer)
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
fix the line as
City.objects.get_or_create(name=city, state=m[0])
you don't need form.save().
Anyway this code is a bit strange, what about your Form?
get_or_create returns two parameters https://docs.djangoproject.com/en/1.7/ref/models/querysets/#django.db.models.query.QuerySet.get_or_create and you can then pass the object straight into the next statement.
state, created = State.objects.get_or_create(name=state)
City.objects.get_or_create(name=state, state=state)
suspect you shouldn't be doing this in form_valid but without rest of your code, can't be sure.

Class Based Generic UpdateView inline

I have the following models
class Cv(models.Model):
name = models.CharField(_('name'), max_length=250)
objective = models.CharField(_('objective'), max_length=250)
slug = models.SlugField(editable=False)
class Position(models.Model):
cv = models.ForeignKey(Cv, verbose_name=_('cv'))
start = models.DateField(_('start'))
end = models.DateField(_('end'))
name = models.CharField(_('name'), max_length=250)
currently_employed = models.BooleanField(_('currently employed'))
sector = models.IntegerField(_('sector'), choices=SECTOR_CHOICES)
duties = models.TextField(_('duties'))
and the following forms:
class CvForm(ModelForm):
class Meta:
model = Cv
class PositionForm(ModelForm):
class Meta:
model = Position
widgets = {
'start': DateInput(attrs={'class':'datepicker'}),
'end': DateInput(attrs={'class':'datepicker'}),
}
PositionFormSet = inlineformset_factory(Cv, Position, form=PositionForm, extra=1)
I have created the following Generic CreateView which works great:
class CreateCvView(CreateView):
model = Cv
form_class = CvForm
template_name = 'recruitment/cv/cv_detail.html'
def get_success_url(self):
self.success_url = '/'
return self.success_url
def get_context_data(self, **kwargs):
context = super(CreateCvView, self).get_context_data(**kwargs)
if self.request.POST:
context['position_form'] = PositionFormSet(self.request.POST)
else:
context['position_form'] = PositionFormSet(instance=self.object)
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.slug = slugify(self.request.user)
context = self.get_context_data()
position_form = context['position_form']
if position_form.is_valid():
self.object = form.save()
position_form.instance = self.object
position_form.save()
return HttpResponseRedirect(self.get_success_url())
else:
return self.render_to_response(self.get_context_data(form=form))
What I want to do is an UpdateView and so I copied the createview and passed it the slug as follows:
class EditCvView(UpdateView):
model = Cv
form_class = CvForm
template_name = 'recruitment/cv/cv_detail.html'
def get_success_url(self):
self.success_url = '/'
return self.success_url
def get_context_data(self, **kwargs):
context = super(EditCvView, self).get_context_data(**kwargs)
if self.request.POST:
context['position_form'] = PositionFormSet(self.request.POST)
else:
context['position_form'] = PositionFormSet(instance=self.object)
return context
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.slug = slugify(self.request.user)
context = self.get_context_data()
position_form = context['position_form']
if position_form.is_valid():
self.object = form.save()
position_form.instance = self.object
position_form.save()
return HttpResponseRedirect(self.get_success_url())
else:
return self.render_to_response(self.get_context_data(form=form))
It loads fine but when I post the form I get a 'list index out of range' error on PositionFormSet(self.request.POST) in get_context_data. Has anyone else had this problem?
in EditCvView:
context['position_form'] = PositionFormSet(self.request.POST, instance=self.object)