Django retrieving postdata - django

I'm having trouble getting ahold of postdata. For some reason the postdata in the following function returns an empty dict. I have a shopping cart, which I'd like users to pass their shipping preference and calculate the total based on the field passed.
My Form:
class ProductAddToCartForm(forms.Form):
""" form class to add items to the shopping cart """
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2', 'value':'1', 'style':'width: 40px;'}),
error_messages={'invalid':'Please enter a valid quantity.'},
min_value=1)
product_slug = forms.CharField(widget=forms.HiddenInput())
shipping = forms.BooleanField(initial=True, required=False)
def __init__(self, request=None, *args, **kwargs):
""" override the default so we can set the request """
self.request = request
super(ProductAddToCartForm, self).__init__(*args, **kwargs)
def clean(self):
""" custom validation to check for presence of cookies in customer's browser """
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError("Cookies must be enabled.")
return self.cleaned_data
My View:
def show_cart(request, template_name="cart/cart.html"):
if request.method == 'POST':
postdata = request.POST.copy()
if postdata['submit'] == 'Remove':
cart.remove_from_cart(request)
if postdata['submit'] == 'Update':
cart.update_cart(request)
if postdata['submit'] == 'Checkout':
checkout_url = checkout.get_checkout_url(request)
return HttpResponseRedirect(checkout_url)
cart_items = cart.get_cart_items(request)
page_title = 'Shopping Cart'
cart_subtotal = cart.cart_subtotal(request)
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
Function requiring postdata:
def cart_subtotal(request):
cart_total = decimal.Decimal('0.00')
cart_products = get_cart_items(request)
for cart_item in cart_products:
cart_total += cart_item.product.price * cart_item.quantity
return cart_total

Related

Handling form fields in django for logged in user

Im trying to handle the existing name of a Category, so that users wont be allowed to create 2 categories with the same name, but at the moment its taking all categories from the database, not only for the logged-in user. I dont know how and where to implement request.user.
I`m building an inventory app where everyone creates their own categories and adds items.
Thank you.
This is my model:
class Category(models.Model):
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE,
related_name='category', null=True)
name = models.CharField(max_length=100, null=False, blank=False)
slug = models.SlugField(max_length=100)
created_on = models.DateTimeField(auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-timestamp']
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('category_detail', kwargs={'slug': self.slug})
This is my form:
class CategoryForm(forms.ModelForm):
add_category = forms.BooleanField(widget=forms.HiddenInput, initial=True)
class Meta:
model = Category
fields = ['name']
def clean_name(self):
name = self.cleaned_data.get('name')
if (name == ""):
raise forms.ValidationError('This field cannot be left blank')
for instance in Category.objects.all():
if instance.name == name:
raise forms.ValidationError('There is a category with the name ' + name)
return name
This is my view:
#login_required
def index(request):
categories = Category.objects.filter(user=request.user)
items = Item.objects.all()
add_item = ItemForm()
add_category = CategoryForm()
query = None
if request.method == 'POST':
if 'add_item' in request.POST:
add_item = ItemForm(request.POST)
if add_item.is_valid():
form = add_item.save(commit=False)
form.category = get_object_or_404(
Category, name=request.POST.get('category'),
user=request.user)
add_item.save()
return redirect('home')
else:
add_category = CategoryForm(request.POST)
if add_category.is_valid():
category_form = add_category.save(commit=False)
category_form.save()
messages.success(request, f'{name} has been added')
return redirect('home')
Edit Category View
#login_required
def category_edit(request, pk):
category = Category.objects.get(id=pk)
if request.method == 'POST':
form = CategoryForm(request.POST, instance=category)
if form.is_valid():
form.save()
messages.info(request, f'{category.name} has been updated!')
return redirect('home')
else:
form = CategoryForm(instance=category, user=request.user)
context = {
'form': form,
}
return render(request, 'category_edit.html', context)
Ive tried adding user = request.user in the form class, but that resulted in an error Ive tried adding category_form.user = request.user before saving the form but that was still taking names from every other user
Pass the request's user to the form:
class CategoryForm(forms.ModelForm):
add_category = forms.BooleanField(widget=forms.HiddenInput, initial=True)
def __init__(self, user, *args, **kwargs):
self.user = user
super().__init__(*args, **kwargs)
class Meta:
model = Category
fields = ['name']
def clean_name(self):
name = self.cleaned_data.get('name')
if (name == ""):
raise forms.ValidationError('This field cannot be left blank')
qs = Category.objects.filter(user=self.user, name=name)
if self.instance.pk:
# EXCLUDE CURRENT INSTANCE TO ENABLE EDIT
qs = qs.exclude(pk=self.instance.pk)
if qs.exists():
raise forms.ValidationError('There is a category with the name ' + name)
return name
then in the view you need to pass the user:
#login_required
def index(request):
categories = Category.objects.filter(user=request.user)
items = Item.objects.all()
add_item = ItemForm()
add_category = CategoryForm(user=request.user)
query = None
if request.method == 'POST':
if 'add_item' in request.POST:
add_item = ItemForm(request.POST)
if add_item.is_valid():
form = add_item.save(commit=False)
form.category = get_object_or_404(
Category, name=request.POST.get('category'),
user=request.user)
add_item.save()
return redirect('home')
else:
add_category = CategoryForm(user=request.user, data=request.POST)
if add_category.is_valid():
category_form = add_category.save(commit=False)
category_form.save()
messages.success(request, f'{name} has been added')
return redirect('home')

Cannot assign "<QuerySet [<Books: Utengano-ut/23>]>": "TeacherIssue.book_id" must be a "Books" instance

I wanted to implement Select2MultipleWidget but I have not managed to succeed in the view. This is what I have but it gives a value error
raise ValueError(
ValueError: Cannot assign "<QuerySet [<Books: Utengano-ut/23>]>": "TeacherIssue.book_id" must be a "Books" instance.
My view
def new_issue(request,pk):
if request.method == 'POST':
form = IssueForm(request.POST,school= request.user.school,pk=pk,issuer = request.user)
if form.is_valid():
print("Form valid")
try:
book = request.POST.getlist('book_id')
#book = form.cleaned_data['book_id'].id
for item in book:
form.cleaned_data[item].id
form.save(commit=True)
books = Books.objects.filter(id__in = book).select_related('subject')
for book.id in books:
Books.Claimbook(book)
return redirect('all_borrowed_teacher', borrowed=borrowed)
except Exception as e:
return redirect('teachers')
else:
form = IssueForm(school= request.user.school,pk=pk,issuer = request.user)
return render(request, 'lib.html', {'form': form})
This is the form
class IssueForm(forms.ModelForm):
def __init__(self,*args, pk, **kwargs):
super(IssueForm, self).__init__(*args, **kwargs)
self.fields["book_id"] = forms.ModelMultipleChoiceField(queryset=Books.objects.all(), widget=Select2MultipleWidget)
class Meta:
model = TeacherIssue
fields = ['book_id']

adding initial value to Django model form

I just want to add an initial value to one field when it gets populated, this is my view
def add_program(request):
module = Module.objects.all()
last_item = Programme.objects.filter(module_id__in=module).last()
if last_item:
day = last_item.day + 1
else:
day = 1
initial_data = {
'day': day
}
if request.method == 'POST':
form = ProgramAddForm(request.POST or None, request.FILES or None, initial=initial_data)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return redirect('program_add')
else:
form = ProgramAddForm()
return render(request, 'client_apps/program/form.html', {'form': form})
and form
class ProgramAddForm(forms.ModelForm):
class Meta:
model = Programme
fields = ['module', 'day', .........]
even though initial value is passed nothing is visible in day field when form populates, is there any alternative method?
That is because you only use it in case of the POST request, not the GET request:
def add_program(request):
module = Module.objects.all()
last_item = Programme.objects.filter(module_id__in=module).last()
if last_item:
day = last_item.day + 1
else:
day = 1
initial_data = {
'day': day
}
if request.method == 'POST':
form = ProgramAddForm(request.POST, request.FILES, initial=initial_data)
if form.is_valid():
instance = form.save()
return redirect('program_add')
else:
form = ProgramAddForm(initial=initial_data) # &leftarrow; initial data for a GET request
return render(request, 'client_apps/program/form.html', {'form': form})
you can add it in the init method
class ProgramAddForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(YoutubeModelForm, self).__init__(*args, **kwargs)
self.fields["day"].value = "day"
self.fields["day"].initial = "day"
self.fields["day"].initial = "padding-top: 0;"
class Meta:
model = Programme
this to load in the form and in the admin of django

form error using cleaned data

I am trying to modify an app that I have found on the net in order to create surveys but I am getting an error that I do not manage to solve
form.py:
def save(self, commit=True):
import pdb; pdb.set_trace()
""" Save the response object """
# Recover an existing response from the database if any
#  There is only one response by logged user.
response = self._get_preexisting_response()
if response is None:
response = super(ResponseForm, self).save(commit=False)
response.survey = self.survey
response.interview_uuid = self.uuid
if self.user.is_authenticated():
response.user = self.user
response.save()
# response "raw" data as dict (for signal)
data = {
'survey_id': response.survey.id,
'interview_uuid': response.interview_uuid,
'responses': []
}
# create an answer object for each question and associate it with this
# response.
for field_name, field_value in self.cleaned_data.items():
if field_name.startswith("question_"):
# warning: this way of extracting the id is very fragile and
# entirely dependent on the way the question_id is encoded in
# the field name in the __init__ method of this form class.
q_id = int(field_name.split("_")[1])
question = Question.objects.get(pk=q_id)
answer = self._get_preexisting_answer(question)
if answer is None:
answer = Answer(question=question)
if question.type == Question.SELECT_IMAGE:
value, img_src = field_value.split(":", 1)
# TODO
answer.body = field_value
data['responses'].append((answer.question.id, answer.body))
LOGGER.debug(
"Creating answer for question %d of type %s : %s", q_id,
answer.question.type, field_value
)
answer.response = response
answer.save()
survey_completed.send(sender=Response, instance=response, data=data)
return response
views.py
class SurveyDetail(View):
#import pdb; pdb.set_trace()
def get(self, request, *args, **kwargs):
survey = get_object_or_404(Survey, is_published=True, id=kwargs['id'])
if survey.template is not None and len(survey.template) > 4:
template_name = survey.template
else:
if survey.display_by_question:
template_name = 'survey/survey.html'
else:
template_name = 'survey/one_page_survey.html'
if survey.need_logged_user and not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
categories = Category.objects.filter(survey=survey).order_by('order')
form = ResponseForm(survey=survey, user=request.user,
step=kwargs.get('step', 0))
context = {
'response_form': form,
'survey': survey,
'categories': categories,
}
return render(request, template_name, context)
def post(self, request, *args, **kwargs):
import pdb; pdb.set_trace()
survey = get_object_or_404(Survey, is_published=True, id=kwargs['id'])
if survey.need_logged_user and not request.user.is_authenticated():
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
categories = Category.objects.filter(survey=survey).order_by('order')
form = ResponseForm(request.POST, survey=survey, user=request.user,
step=kwargs.get('step', 0))
context = {'response_form': form, 'survey': survey,
'categories': categories}
if form.is_valid():
session_key = 'survey_%s' % (kwargs['id'],)
if session_key not in request.session:
request.session[session_key] = {}
for key, value in form.cleaned_data.items():
request.session[session_key][key] = value
request.session.modified = True
next_url = form.next_step_url()
response = None
if survey.display_by_question:
if form.has_next_step():
save_form = ResponseForm(request.session[session_key],
survey=survey, user=request.user)
response = save_form.save(request)
else:
response = form.save()
if next_url is not None:
return redirect(next_url)
else:
del request.session[session_key]
if response is None:
return redirect('/')
else:
next_ = request.session.get('next', None)
if next_ is not None:
if 'next' in request.session:
del request.session['next']
return redirect(next_)
else:
return redirect('survey-confirmation',
uuid=response.interview_uuid)
if survey.template is not None and len(survey.template) > 4:
template_name = survey.template
else:
if survey.display_by_question:
template_name = 'survey/survey.html'
else:
template_name = 'survey/one_page_survey.html'
return render(request, template_name, context)
the weired thing is that I get the error AttributeError: 'ResponseForm' object has no attribute 'cleaned_data' even if the form got the is_valid attribute
.cleaned_data is only available once you call .is_valid() on the form.
Most likely you haven't called is_valid() on the form in your view yet.

How to write an update view with formset_factory

I love how I can pass an instance to a form and it will populate it on a page. The trouble I am having is with formset_factory. I am trying to use query_set...
def classroom_update(request, pk):
classroom = get_object_or_404(Classroom, pk=pk)
students = classroom.student_set.all()
# Empty formset forms should be required
class RequiredFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(RequiredFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
#StudentFormSet = inlineformset_factory(Classroom, Student)
StudentFormSet = formset_factory(StudentForm, max_num=100, formset=RequiredFormSet)
if request.method == 'POST': # If the form has been submitted...
classroom_form = ClassroomForm(request.POST)
student_formset = StudentFormSet(request.POST, request.FILES)
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False)
classroom.user = request.user
classroom.save()
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom
student.save()
return HttpResponseRedirect('/') # Redirect to a 'success' page
else:
classroom_form = ClassroomForm(instance=classroom)
student_formset = StudentFormSet(query_set=students)
# For CSRF protection
# See http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
c = {'classroom_form': classroom_form,
'student_formset': student_formset,
}
c.update(csrf(request))
return render_to_response('reports/modify_classroom.html', c)
EDIT: Here is the error message...
formset_factory() got an unexpected keyword argument 'query_set'
Apparently I don't know how to use query_set...