django formset initial data not coming - django

this is my model :
class Member(models.Model):
profile = models.OneToOneField(Profile, editable=False, null=True)
title = models.CharField(max_length=4, choices=TITLE_TYPES, null=True)
name = models.CharField(max_length=100, null=True, verbose_name='Name')
lastname = models.CharField(max_length=100, null=True, verbose_name='LastName')
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, null=True, verbose_name='Gender')
dob = models.DateField('dob')
redressno = models.CharField(max_length=100, null=True, verbose_name='RedressNo')
this is my form
class MemberForm(ModelForm):
dob = forms.DateField(required=False, input_formats=('%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y'))
class Meta:
model = Member
exclude = ('profile',)
this is my view :
members = Member.objects.filter(profile=profiles)
data1 = serializers.serialize( "python", members)
print data1[0]['fields']
memarr=[]
for index, a in enumerate(data1):
memarr.append(a['fields'])
print memarr
MemberFormSet = formset_factory(MemberForm, formset=BaseFormSet)
member_formset = MemberFormSet(initial=memarr)
#here setting intial array of mem
mdata['form-TOTAL_FORMS']=u'2'
mdata['form-INITIAL_FORMS']=u'0'
mdata['form-MAX_NUM_FORMS']=u''
member_formset = MemberFormSet(mdata)
memberform = MemberForm(mdata)
c = {'form': form, 'memberform': memberform, 'member_formset': member_formset}
c.update(csrf(request))
return render_to_response('edit_profile.html', c, RequestContext(request))
m passing the initial data but still the initial data is not being shown in the form?

Here's your problem:
member_formset = MemberFormSet(initial=memarr)
...
member_formset = MemberFormSet(mdata)
You're setting the initial data on one FormSet instance, and then throwing away that instance with the initial data and overwriting with another new FormSet instance.
You can simplify your view to this:
# If you are not using csrf middleware, use this decorator instead of ghetto magic
#csrf_protect
#render_to('edit_profile.html') # handy decorator from django-annoying
def profile_members_edit(request.profile):
members = Member.objects.filter(profile=profiles)
# iterate over the ValuesQuerySet gives a list of dicts for initial data
member_data = list(members.values())
# setting extra=<> and max_num=<> is easier than setting internal form data
MemberFormSet = formset_factory(MemberForm, formset=BaseFormSet, extra=2)
member_formset = MemberFormSet(initial=member_data)
return {'member_formset': member_formset }

Related

django form commit=false after how to save many to many field data

Model.py
class Branch(models.Model): # Branch Master
status_type = (
("a",'Active'),
("d",'Deactive'),
)
name = models.CharField(max_length=100, unique=True)
suffix = models.CharField(max_length=8, unique=True)
Remark = models.CharField(max_length=200, null=True, blank=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, choices = status_type, default = 'a')
def __str__(self):
return self.name
class Vendor(models.Model):
status_type = (
("a",'Active'),
("d",'Deactive'),
)
branch = models.ManyToManyField(Branch)
company = models.CharField(max_length=200)
name = models.CharField(max_length=200)
phone = models.CharField(max_length=11, unique = True)
email = models.EmailField(max_length=254, unique = True)
gst = models.CharField(max_length=15, unique = True)
pan_no = models.CharField(max_length=10, unique = True)
add_1 = models.CharField(max_length=50, null=True, blank = True)
add_2 = models.CharField(max_length=50, null=True, blank = True)
add_3 = models.CharField(max_length=50, null=True, blank = True)
Remark = models.CharField(max_length=200, null=True, blank=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
create_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, choices = status_type, default = 'a')
def __str__(self):
return self.company
form.py
i want save like created_by field
class VendorForm(ModelForm):
class Meta:
model = Vendor
fields = 'all'
exclude = ['created_by', 'branch']
widgets = {
'company':forms.TextInput(attrs={'class':'form-control'}),
'name':forms.TextInput(attrs={'class':'form-control'}),
'phone':forms.TextInput(attrs={'class':'form-control'}),
'email':forms.EmailInput(attrs={'class':'form-control'}),
'gst':forms.TextInput(attrs={'class':'form-control'}),
'pan_no':forms.TextInput(attrs={'class':'form-control'}),
'add_1':forms.TextInput(attrs={'class':'form-control'}),
'add_2':forms.TextInput(attrs={'class':'form-control'}),
'add_3':forms.TextInput(attrs={'class':'form-control'}),
'Remark':forms.Textarea(attrs={'class':'form-control','rows':'2'}),
'status':forms.Select(attrs={'class':'form-control'}),
}
Views.py
I have pass branch in session.
I want to save with branch which is many to many field
def Add_Vendor(request): # for vendor add
msg = ""
msg_type = ""
branch_id = request.session['branch_id']
branch_data = Branch.objects.get(id = branch_id)
form = ""
if request.method == "POST":
try:
form = VendorForm(request.POST)
if form.is_valid:
vendor_add = form.save(commit=False)
vendor_add.created_by = request.user
vendor_add.instance.branch = branch_data.id
vendor_add.save()
form.save_m2m() # for m to m field save
msg_type = "success"
msg = "Vendor Added."
form = VendorForm(initial={'branch':branch_id})
except:
msg_type = "error"
msg = str(form.errors)
print(msg)
else:
form = VendorForm(initial={'branch':branch_id})
context = {
'form':form,
'branch_data':branch_data,
'msg_type':msg_type,
'msg':msg,
'btn_type':'fa fa-regular fa-plus',
'form_title':'Vendor Form',
'tree_main_title':'Vendor',
'v_url':'vendor_page',
'tree_title':'Add Form',
}
return render(request, 'base/vendor_master/form_vendor.html',context)
I would advise not to work with commit=False in the first place:
def Add_Vendor(request): # for vendor add
branch_id = request.session['branch_id']
branch_data = get_object_or_404(Branch, pk=branch_id)
if request.method == 'POST':
form = VendorForm(request.POST, request.FILES)
if form.is_valid():
form.instance.created_by = request.user
form.instance.branch = branch_data.id
vendor_add = form.save()
vendor_add.branch.add(branch_data)
return redirect('name-of-some-view')
else:
form = VendorForm()
context = {
'form': form,
'branch_data': branch_data,
'btn_type': 'fa fa-regular fa-plus',
'form_title': 'Vendor Form',
'tree_main_title': 'Vendor',
'v_url': 'vendor_page',
'tree_title': 'Add Form',
}
return render(request, 'base/vendor_master/form_vendor.html', context)
You can simplify your form by automatically adding form-control to each widget:
class VendorForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
attrs = field.widget.attrs
attrs['class'] = attrs.get('class', '') + ' form-control'
class Meta:
model = Vendor
exclude = ['created_by', 'branch']
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can set a field editable=False [Django-doc]. Then the field does not show up in the ModelForms and ModelAdmins by default. In this case for example with created_by.
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.
Note: Please do not pass messages manually to the template. Django has the messages framework [Django-doc], which allows to add messages to the request, which will then be delivered the next time a template renders these messages. This makes delivering multiple messages convenient, as well as setting different log levels to the messages.

Saving many-to-many fields from the excel file in Django

I'm trying to save the student data from an excel file. I'm reading the excel file row-wise and mapping the data to the model fields. Now the problem is that there is a foreign key and a many-to-many field which I don't know how to save. Though I figured out the foreign key part but not able to solve the second part.
Here are the files.
views.py
def fileUpload(request):
if request.method=="POST":
form= UserDataUploadView(request.POST, request.FILES)
try:
excel_file= request.FILES["excel_file"]
except MultiValueDictKeyError: # In case the user uploads nothing
return redirect('failure_page')
# Checking the extension of the file
if str(excel_file).endswith('.xls'):
data= xls_get(excel_file, column_limit=10)
elif str(excel_file).endswith('.xlsx'):
data= xlsx_get(excel_file, column_limit=10)
else:
return redirect('failure_page')
studentData= data["Sheet1"]
print("Real Data", studentData)
# reading the sheet row-wise
a_list= studentData
list_iterator= iter(a_list)
next(list_iterator)
for detail in list_iterator:
# To find out empty cells
for data in detail:
if data==" ":
print('A field is empty')
return redirect('user_upload')
print("DATA: ", detail)
user=User.objects.create(
firstName = detail[6],
lastName = detail[7],
password = detail[8],
username = detail[9],
)
# instance=user.save(commit=false)
# Student.batch.add(detail[0])
student=Student.objects.create(
user = user,
email = detail[1],
rs_id = detail[2],
dob = detail[3],
address = detail[4],
age = detail[5],
)
student.save()
return render(request, 'classroom/admin/success_page.html', {'excel_data':studentData})
# iterating over the rows and
# getting value from each cell in row
# for row in worksheet.iter_rows():
# row_data= list()
# for cell in row:
# row_data.append(str(cell.value))
# excel_data.append(row_data)
# return render(request, 'classroom/admin/excel.html', {'excel_data':excel_data})
else:
form=UserDataUploadView()
return render(request, 'classroom/admin/fill_users.html', {
'form':form,
# 'excel_data':excel_data,
})
models.py
class Subject(models.Model):
school = models.CharField(max_length=50, null=True)
name = models.CharField(max_length=30)
color = models.CharField(max_length=7, default='#007bff')
def __str__(self):
return self.name
def get_html_badge(self):
name = escape(self.name)
color = escape(self.color)
html = '<span class="badge badge-primary" style="background-color: %s">%s</span>' % (color, name)
return mark_safe(html)
class Batch(models.Model):
name = models.CharField(max_length=30, unique=True)
school = models.CharField(max_length=50)
amount_of_fees = models.IntegerField(null=True)
subjects = models.ManyToManyField(Subject)
#property
def students(self):
return self.student_set.all()
def __str__(self):
return self.name
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
batch = models.ManyToManyField(Batch)
email = models.EmailField(null=True)
phone_number = models.CharField(max_length=10, null=True)
dob = models.DateField(blank=True, null=True, help_text="Enter in the following format : YYYY-MM-DD")
address = models.TextField(max_length=150, null=True)
age = models.IntegerField(blank=True)
image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)
rs_id = models.IntegerField(blank=True,default=0)
I don't know how to put the data for batch in the excel sheet. Kindly give insight for that too.
Assuming detail[0] is the name field for the Batch model, you would do:
student_batch = Batch.objects.get(name=detail[0])
student=Student.objects.create(
user = user,
email = detail[1],
rs_id = detail[2],
dob = detail[3],
address = detail[4],
age = detail[5],
)
student.batch.add(student_batch)
student.save()
You will also need to update your Batch field on the Student model to:
batch = models.ManyToManyField(Batch, blank=True)

How to fill empty fields when I save form from POST

I try to fill empty fields when I save model form, but unfortunately, it doesn't work properly.
this is my view:
def bylaw_save(request):
form = BylawForm(initial={'who_created': request.user.username})
if request.method == 'POST':
form = BylawForm(request.POST)
if form.is_valid():
gdn = GlobalDocNumber.objects.get(pk=1)
gdn.gdn += 1
gdn.save()
raspr_num = form.cleaned_data['raspr_num'][:]
raspr_num = raspr_num.split('/')
bylaw = form.save(commit=False)
bylaw.district = 'unfilled'
bylaw.department = 'unfilled'
bylaw.performer = 'unfilled'
bylaw.check_type = 'unfilled'
bylaw.save()
return bylaw_form(request, msg='test')
else:
return bylaw_form(request, msg='test')
return render(request, 'bylaw/bylaw_form.html', {'form': form})
this is fraction of my form:
district = ModelChoiceField(required=False, queryset=DistrictsMenu.objects.all(), to_field_name="district",
widget=Select(attrs={'id': "district", 'class': 'form-control col-6'}))
department = ModelChoiceField(required=False, queryset=DepartmentsMenu.objects.all(), to_field_name="department",
widget=Select(attrs={'id':"department", 'class': "form-control col-6"}))
UPDATE: This is my model with default='Unfilled', according to Arthur M and Rohan suggestions (But it also doesn't work, it gives me a "NOT NULL constraint failed: bylaw_bylawmodel.department" error, in this case I don't fill department field):
class BylawModel(models.Model):
raspr_date = models.DateField()
district = models.CharField(max_length=255, default='Unfilled')
department = models.CharField(max_length=255, default='Unfilled')
organization = models.CharField(max_length=255, default='Unfilled')
inn = models.IntegerField()
performer = models.CharField(max_length=255, default='Unfilled')
check_type = models.CharField(max_length=255)
date_proved = models.DateField()
raspr_num = models.CharField(max_length=255, unique=True)
who_created = models.CharField(max_length=255)
when I save this from, it always fills with 'unfilled'. How can I fill empty values only if they are really empty?
By doing
bylaw.fieldName = 'unfilled' you're overwriting the value sent from your form.
If you don't want to add a default value in your model (which I would recommend) you can add a simple :
if not bylaw.fieldName:
bylaw.fieldName = 'unfilled'
For every one of your fields.

Forms in Django. How to initialize model field from form?

In models.py:
class Client(AbstractBaseUser):
username = models.CharField(max_length=32, unique=True)
email = models.EmailField('email address', unique=True, db_index=True)
avatar = models.ImageField('avatar', upload_to='avatars')
id = id(object)
class Order(models.Model):
class Meta():
db_table = 'order'
short_desc = models.CharField(max_length=30)
subject = models.ForeignKey(Subject, blank=True)
user_id = models.ForeignKey('Client', to_field='id', related_name='client_id', default='0', blank=True)
performer_id = models.ForeignKey('Client', to_field='id', related_name='performer_id', default='0', blank=True)
worktype = models.ForeignKey(Type, blank=True)
level = models.IntegerField(default=0, blank=True)
readiness = models.BooleanField(default=False, blank=True)
description = models.TextField(max_length=2000, blank=True)
file = models.FileField(upload_to='orderfiles', blank=True)
#maxdate = models.DateField(blank=True)
addate = models.DateField(auto_now=True, blank=True)
price = models.IntegerField(max_length=10, blank=True)
responses = models.IntegerField(blank=True)
In forms.py:
class AddOrderForm(forms.ModelForm):
short_desc = forms.CharField(widget=forms.TextInput,label="Краткое описание(послужит именем)")
subject = forms.ModelChoiceField(queryset=Subject.objects.all(), label="Предмет")
worktype = forms.ModelChoiceField(queryset=Type.objects.all(), label="Тип")
level = forms.IntegerField(widget=forms.TextInput,label="Уровень сложности (от 1 до 5)")
description = forms.CharField(widget=forms.TextInput,label="Полное описание")
#maxdate = forms.DateField(widget=forms.TextInput,label="maxdate")
price = forms.IntegerField(widget=forms.TextInput,label="Ваша цена")
responses = forms.IntegerField(widget=forms.TextInput,label="Кол-во ответов на заказ")
class Meta:
model = Order
fields = ['short_desc', 'level', 'description', 'price', 'responses', 'subject', 'worktype']
In views.py:
def addorder(request, user_id):
"""
Adding Order view
"""
if request.POST:
form = AddOrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
return redirect('/')
auth1 = auth.get_user(request).username
return render_to_response('customer.html', { 'form': form,'username' : auth1}, context_instance=RequestContext(request))
I need the field user_id in class Order to be initialized immediately after adding order(). Where should I do it and in which way? I need something like this logic: Client adds an Order through AddOrderForm and then user_id field of just added object of class Order has to be initialized with an object of class Client, whose id equals user_id in parameters of addorder() function.
You can do that using commit=False while saving the form. This is typical way of saving the object using model form which has fewer fields.
def addorder(request, user_id):
"""
Adding Order view
"""
if request.POST:
form = AddOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=false)
order.client_id = Client.objects.get(id=user_id)
order.save()
return redirect('/')
else:
return redirect('/')
auth1 = auth.get_user(request).username
return render_to_response('customer.html',
{ 'form': form,'username' : auth1},
context_instance=RequestContext(request))
Disclaimer: Handle errors e.g. Client.objects.get() may fail. Use appropriate fields to search.

Extend class-based UpdateView to rate objects

I have the following models that I need to create a form which allows for the updating of an existing Response (generated previously with a slug and then emailed to the respondent) and the creation of a Rating for each CV in CV.objects.all(). What's the easiest way to do this in Django. Currently I have a class-based UpdateView for Response and that's it.
class Response(models.Model):
first_name = models.CharField(max_length=200, null=True, blank=True)
last_name = models.CharField(max_length=200, null=True, blank=True)
email = models.EmailField(max_length=254)
slug = models.SlugField(max_length=32)
submited = models.BooleanField(default=False)
submit_time = models.DateTimeField(null=True, blank=True)
creation_time = models.DateTimeField(auto_now_add=True)
class CV(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(upload_to=content_file_name)
class Rating(models.Model):
cid = models.ForeignKey('CV')
rid = models.ForeignKey('Response')
score = models.IntegerField()
comment = models.TextField()
I eventually worked out how to do this. My code was as follows in case anyone is interested.
def add_response(request):
CVs = CV.objects.all()
if request.method == "POST":
ResForm = ResponseForm(request.POST, instance=Response())
RatForms = [RatingForm(request.POST, prefix=str(cv.id), instance=Rating(cid=cv)) for cv in CVs]
if ResForm.is_valid() and all([rf.is_valid() for rf in RatForms]):
new_response = ResForm.save(commit=False)
new_response.submit_time = datetime.now()
new_response.submited = True
new_response.save()
for rf in RatForms:
new_rating = rf.save(commit=False)
new_rating.rid = new_response
new_rating.save()
return HttpResponseRedirect('/thanks/')
else:
for i, _ in enumerate(RatForms):
RatForms[i].cv = CV.objects.filter(id=int(RatForms[i].prefix))[0]
print RatForms[i].cv
return render(request, 'response.html', {'response_form': ResForm, 'rating_forms': RatForms})
else:
ResForm = ResponseForm(instance=Response())
RatForms = [RatingForm(prefix=str(cv.id), instance=Rating(cid=cv)) for cv in CVs]
for i, _ in enumerate(RatForms):
RatForms[i].cv = CV.objects.filter(id=int(RatForms[i].prefix))[0]
print RatForms[i].cv
return render(request, 'response.html', {'response_form': ResForm, 'rating_forms': RatForms})