I create a financial manager and I need the user to change the account activity (indicate an active account or not), but when I send the form for change, then the model attribute does not change and always remains TRUE
I also tried to do this through a copy of the Account, but it was also not a result of the outcome
Account.objects.get(user=self.request.user, id=id).is_active = False
models.py
class Account(models.Model):
type_of_currency = models.CharField(max_length=20)
user = models.ForeignKey(get_user_model(), blank=True,
related_name='user_account',
on_delete=models.CASCADE)
count = models.DecimalField(max_digits=12, decimal_places=2, blank=True)
created = models.DateTimeField(default=datetime.datetime.now)
is_active = models.BooleanField()
def __str__(self):
return f'{self.type_of_currency} - {self.count}'
views.py
class AccountDetailView(DetailView, UpdateView):
model = Account
form_class = AccountCreateForm
template_name = 'account_detail.html'
def post(self, request, *args, **kwargs):
id = self.request.POST['accountid']
self.request.user.user_account.get(id=6).is_active = False
print(self.request.user.user_account.get(
id=id).is_active) # always True why?
return redirect('/counts/' + id)
template
{% extends 'base.html' %}
{% block content %}
<div class="col-sm-5">
<h1>account: {{ account.id }}</h1>
<p><strong>Author:</strong> {{ account.user }}</p> <!-- author detail link not yet defined -->
<p><strong>Type:</strong> {{ account.type_of_currency }}</p>
<p><strong>count:</strong> {{ account.count }}</p>
<p><strong>IsCreated:</strong> {{ account.created }}</p>
<p><strong>IsActive:</strong>{{ account.is_active }}</p>
<a class="btn btn-outline-primary"
href="{% url 'account-list' %}">Back</a>
{% if account.is_active %}
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ account.id }}" name="accountid">
<button type="submit" class="btn btn-outline-danger">Deactivate</button>
</form>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-outline-success">Activate</button>
</form>
{% endif %}
</div>
{% endblock %}
In the post method DetailViews, I expect that after the button is pressed, user activity will change, but the result is always True
You're never commiting change to DB.
Also, I wouldn't use the following syntax: self.request.user.user_account.get(id=6).is_active = False
You can try: self.request.user.user_acocount.filter(id=6).update(is_active=False)
But, if you're dead set on using .get():
user_acc = self.request.user.user_account.get(id=6)
user_acc.is_active = False
user_acc.save()
Related
I created view where i add stops to route, its working fine, but stops are not appearing in order when i add them, and i have no idea why. Please tell me where i'm making a mistake
Here's my code:
Models:
class Port(models.Model):
name = models.CharField(max_length=128)
description = models.TextField(default='')
lattitude = models.DecimalField(max_digits=9, decimal_places=6)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
amenities = models.ManyToManyField(Amenity, blank=True)
def __str__(self):
return f'{self.name}'
class Route(models.Model):
name = models.CharField(max_length=128, default='')
user = models.ForeignKey(User, on_delete=models.CASCADE)
stop_list = models.ManyToManyField(Port, through='RoutePort')
def __str__(self):
return f'{self.name}'
class RoutePort(models.Model):
port = models.ForeignKey(Port, on_delete=models.CASCADE)
route = models.ForeignKey(Route, on_delete=models.CASCADE)
order = models.PositiveIntegerField()
class Meta:
ordering = ['order']
the order i intend them to appear is set by 'order' parameter from class routeport
form:
class AddRoutePort(forms.ModelForm):
class Meta:
model = RoutePort
fields = ['port', 'order']
form is short and i dont know if i didnt forget something there
View, get is working correctly, post works almost ok. New ports are correctly added to new route from list, but they appear in order of being added, not the one i wanted them to.
class RouteCorrectView(View):
def get(self, request, pk):
route = Route.objects.get(pk=pk)
form = AddRoutePort()
return render(request, 'route_correct.html', {'route':route, 'form':form})
def post(self, request, pk):
route = Route.objects.get(pk=pk)
form = AddRoutePort(request.POST)
if form.is_valid():
to_port = form.save(commit=False)
to_port.route = route
order = to_port.order
ordering = RoutePort.objects.filter(order__gte=order, route=route)
for port in ordering:
port.order += 1
port.save()
to_port.save()
return redirect('route_correct', pk)
return render(request, 'route_correct.html', {'route':route, 'form':form})
and HTML - i can't draw set order here, so i think theres a mistake somwhere previously. Line {{ stops.order }} does nothing.
{% extends 'base.html' %}
{% block content %}
<div class="card">
<ul>Nazwa</ul>
<p>{{ route.name }}</p>
<ul>Twórca</ul>
<p> {{ route.user }}</p>
<ul>Szlak</ul>
<td> {% for stops in route.stop_list.all %}
{{ stops }} {{ stops.order }}
<td>
<form action="{% url 'delete_stop' stops.id %}" method="get"> {% csrf_token %}
<input type="submit">usuń</form>
<form action="{% url 'port_detail' stops.id %}" method="get"> {% csrf_token %}
<input type="submit">o porcie</form><br>
</td>
{% empty %}
Szlak jest jeszcze pusty
{% endfor %}</td>
</div>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
</div>
{% endblock %}
So i found the solution. First of all i'm an idiot, second of all - html was problem
<td> {% for stops in route.stop_list.all %}
{{ stops }} {{ stops.order }}
<td>
Above part refer to stop list, not routeport model with "order" in it. It should look like that:
<td> {% for stops in route.routeport_set.all %}
{{ stops.port }} {{ stops.order }}
<td>
where i refer to routeport with order in it.
I'm trying to filter a model called "CartItem" , that has a field called item , I want to check whether a product id is in this field. each cartitem instance is connected to a cart.id. The product id is taken from a form in templates.
I currently have " {% if cartitem.objects.filter(item_id=product_id).exists %} " in the template, I also tried making an items list in the views.py , to try to use the "if in" statement in the template, based off the "items" contents, the only problem was that when the browser is refreshed the for loop to create this list is not called , it is only called when the user clicks on the "add to cart" button. Hope that makes sense.
at the moment I get an error:
TemplateSyntaxError
Exception Value:
Could not parse the remainder: '(item.id=product.id).exists' from 'cartitem.objects.filter(item.id=product.id).exists'
Thanks
models.py
class CartItem(models.Model):
item = models.ForeignKey(Product, blank=True, on_delete=models.CASCADE, null=True)
items_cart = models.ForeignKey('Cart', blank=True, on_delete=models.CASCADE, null=True)
quantity = models.IntegerField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return 'item:{} cart:{} quantity:{}'.format(self.item, self.items_cart, self.quantity)
views.py
def cart_update(request):
product_id = request.POST.get('product_id')
cart_obj, new_obj = Cart.objects.new_or_get(request)
cart_items = CartItem.objects.filter(items_cart_id=cart_obj)
items = []
for item in cart_items:
items.append(item.item.id)
print(items)
if product_id is not None:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("Show message to user, product is gone?")
return redirect("cart:home")
cart_obj, new_obj = Cart.objects.new_or_get(request)
cart_items = CartItem.objects.filter(items_cart_id=cart_obj)
if product_obj in cart_items:
cart_items.delete(product_obj)
added = False
else:
newitem = CartItem(item=product_obj, items_cart=cart_obj, quantity=1)
newitem.save()
added = True
request.session['cart_items'] = cart_items.count()
# return redirect(product_obj.get_absolute_url())
if request.is_ajax(): # Asynchronous JavaScript And XML / JSON
print("Ajax request")
json_data = {
"added": added,
"removed": not added,
"cartItemCount": cart_items.count()
}
return JsonResponse(json_data, status=200) # HttpResponse
# return JsonResponse({"message": "Error 400"}, status=400) # Django Rest Framework
return redirect("cart:home")
cart.html
<form class='form-product-ajax' method='POST' action='{% url "cart:update" %}' data-endpoint='{% url "cart:update" %}' class="form" {% if request.user.is_authenticated %}data-user='abc'{% endif %}> {% csrf_token %}
<input type='hidden' name='product_id' value='{{ product.id }}' {% if product.is_digital %}data-is-digital='true'{% endif %}/>
<span class='submit-span'>
{% if cartitem.objects.filter(item_id=product_id).exists %}
<div class='btn-group'> <a class='btn btn-link' href='/cart/'>In cart</a> <button type='submit' class='btn btn-link'>Remove?</button></div>
{% else %}
<button type='submit' class='btn btn-success'>Add to cart</button>
{% endif %}
</span>
</form>
you can not use this syntax in template django:
cartitem.objects.filter(item.id=product.id).exists
you can use templatetags and call it in your template:
register = template.Library()
#register.filter
def existing_product(product):
return CartItem.objects.filter(item.id=product.id).exists()
then load your templatetag in your template
{% load file_name_containing_your_method %}
<form class='form-product-ajax' method='POST' action='{% url "cart:update" %}' data-endpoint='{% url "cart:update" %}' class="form" {% if request.user.is_authenticated %}data-user='abc'{% endif %}> {% csrf_token %}
<input type='hidden' name='product_id' value='{{ product.id }}' {% if product.is_digital %}data-is-digital='true'{% endif %}/>
<span class='submit-span'>
{% if product|existing_product %}
<div class='btn-group'> <a class='btn btn-link' href='/cart/'>In cart</a> <button type='submit' class='btn btn-link'>Remove?</button></div>
{% else %}
<button type='submit' class='btn btn-success'>Add to cart</button>
{% endif %}
</span>
</form>
hope this can help your second question
NB: you should reboot your server after adding a templatetag
For one of my open source projects, I need to create ONE add/edit page in order to make possible to edit several records with one save.
The repo is an IMDB clone formed for learning purpose. A user can add her/his favorite genres in her/his profile. Then an edit page is formed to show the list of those favored genres and the movies within that genre. (A for loop here) User can add notes, watch list options and so on to those movies. (NOT a FORMSET)
However, the code doesn't work as expected. The page cannot be saved and only the first checkbox of the list can be changed.
There is no error.
NOTE:
You can install repo with dummy data.
(https://github.com/pydatageek/imdb-clone)
Then after logging in, select your favorite genres. (http://localhost:8000/users/profile/)
Then (I wish it can be solved here) you can see the movies with your selected genres. Add notes, to watch list... (http://localhost:8080/users/profile/movies2/)
# users/templates/user-movies-with_loop.html
{% extends 'base.html' %}{% load crispy_forms_tags %}
<!-- Title -->
{% block htitle %}Your movies from favorite genres{% endblock %}
{% block title %}Your movies from favorite genres{% endblock %}
{% block content %}
<div class="card card-signin">
{% include 'users/profile-menu.html' %}
<h3 class="card-title text-center my-4">Take notes for your movies <small></small></h3>
<hr class="mb-1">
<div class="card-body">
<form method="POST">
{% csrf_token %}
{% for genre in user.genres.all %}
<h2 for="genre" name="genre" value="{{ genre.id }}">{{ genre.name }}</h2>
{% for movie in genre.movies.all %}
<div class="ml-5">
<h4>{{ movie.title }}</h4>
{{ form|crispy }}
</div>
<input type="hidden" name="user" value="{{ user.id }}">
<input type="hidden" name="movie" value="{{ movie.id }}">
{% empty %}
<p class="alert alert-danger">The genre you have selected on your profile doesn't have any movies!</p>
{% endfor %}
{% empty %}
<p class="alert alert-danger">You should select genres with movies from your profile to edit here!</p>
{% endfor %}
<input class="btn btn-lg btn-primary btn-block text-uppercase" type="submit" value="Submit">
</form>
</div>
</div>
{% endblock %}
# users.forms.py
...
class UserMovieFormWithLoop(ModelForm):
genre = forms.HiddenInput(attrs={'disabled': True})
class Meta:
model = UserMovie
fields = ('user', 'movie', 'note', 'watched', 'watch_list')
widgets = {
'user': forms.HiddenInput,
'movie': forms.HiddenInput,
'watched': forms.CheckboxInput(),
}
...
# users.models.py
...
class UserMovie(models.Model):
"""
Users have notes about their favorite movies.
"""
user = models.ForeignKey(User, on_delete=models.CASCADE)
movie = models.ForeignKey('movies.Movie', default=1, on_delete=models.CASCADE)
note = models.CharField(max_length=250, null=True, blank=True)
watched = models.BooleanField(default=False, verbose_name='Have you seen before?')
watch_list = models.BooleanField(default=False, verbose_name='Add to Watch List?')
def __str__(self):
return f'{self.user.username} ({self.movie.title})'
...
# users.views.py
...
class UserMovieViewWithLoop(LoginRequiredMixin, CreateView):
model = UserMovie
template_name = 'users/user-movies-with_loop.html'
form_class = UserMovieFormWithLoop
success_message = 'your form has been submitted.'
success_url = reverse_lazy('users:user_movies2')
def form_valid(self, form):
user = self.request.user
movie_counter = Movie.objects.filter(genres__in=user.genres.all()).count()
f = form.save(commit=False)
f.user = user
for i in range(movie_counter):
f.pk = None
f.save()
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super(UserMovieViewWithLoop, self).get_context_data(**kwargs)
context['form'] = self.form_class
return context
def get_object(self):
user = self.request.user
return UserMovie.objects.get(user=user)
...
need your assistance in figuring out what is wrong with a form in my django app,i have a tab section in my app that has three tabs (lesson,workbook,answer).The work flow is that a user goes through some lesson content then clicks on a "take exercise" button which leads him to the workbook tab.Here i have questions which can either be multiple choice question or easy question depending on the lesson, after completing exercise a user submits the question and he transitions to the answers tab where his submitted answer is displayed in addition to the expected answer if he was wrong.My problem is that when the submit button is clicked the answers are not submitted and hence no user answers are displayed in the answer tab.
Here is the html code
<div class="tabs present-addition">
<!-- Nav tabs -->
<ul class="nav nav-tabs">
<li {% if active_tab == "lesson" %}class="active"{% endif %}>Lesson Content</li>
<li {% if active_tab == "workbook" %}class="active"{% endif %}>Workbook</li>
<li {% if active_tab == "answers" %}class="active"{% endif %}>Answers</li>
</ul>
{% if messages %}
<div>{{ message }}</div>
<!--<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>-->
{% endif %}
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="lesson">
<p>{{ lesson.content|safe }}</p>
<!--<p>View Example</p>-->
{% if lesson.instructions_before %}
<h3>Instructions</h3>
<p>{{ lesson.instructions_before|safe }}</p>
{% endif %}
<div class="btn-container btn-container-info" id="wkbck">
<a class="btn btn-info btn--minimal btn-lg-bordered btn-inverse" href="#" data-toggle="tab" data-target="#workbook" >Take Exercise</a>
</div>
</div>
<div class="tab-pane" id="workbook">
{% if lesson.get_exercises %}
{% for exercise in lesson.get_exercises %}
<h4>{{ exercise.title }}</h4>
<form method="post" action="{% url 'exercise_submit' lesson.id exercise.id %}" class="contact" style="text-align:left;">
{% csrf_token %}
<input type="hidden" id="exercise_id" name="exercise_id" value="{{ exercise.id }}">
{% for question in exercise.question_set.all %}
<h6>{{ question.title }}</h6>
{% for answer in question.num_of_expected_answers|get_range %}
{{ forloop.counter }}: <input type="text" name="qu-{{ question.id }}-{{ forloop.counter }}" id="answer-{{ question.id }}-{{ forloop.counter }}" class="contact__field" style="width: 50%;" required /></br>
{% endfor %}
{% endfor %}
{% for mcquestion in exercise.multichoicequestion_set.all %}
<h6>{{ mcquestion.title }}</h6>
<div class="checkbox">
{% for option in mcquestion.multichoicequestionoption_set.all %}
{% with forloop.counter as curr_counter %}
<input type="checkbox" id="mcq-{{ mcquestion.id }}-{{ curr_counter }}" name="mcq-{{ mcquestion.id }}-{{ curr_counter }}" value="{{ option.content }}" >
<label for="mcq-{{ mcquestion.id }}-{{ curr_counter }}">{{ option.content }}</label>
{% endwith %}
{% endfor %}
</div>
</br>
{% endfor %}
{% for essay_question in exercise.essayquestion_set.all %}
<h6>{{ essay_question.title }}</h6>
<div class="modal-body">
<textarea rows="6" cols="50" class="contact__field contact__area" style="width: 50%;" name="eq-{{ essay_question.id }}" id="eq-{{ essay_question.id }}" placeholder="Type your answer here" required></textarea>
</div>
</br>
{% endfor %}
<div class="btn-container btn-container-info">
<button type="sumbit" class="btn btn-info btn--minimal btn-lg-bordered btn-inverse" data-toggle="tab" data-target="#answers" >Submit</button>
</div>
</form>
{% endfor %}
{% endif %}
<p>
<!--<div class="btn-container btn-container-info">
<a class="btn btn-info btn--minimal btn-lg-bordered btn-inverse" href="#"> Submit </a>
</div>-->
</p>
</div>
<div class="tab-pane" id="answers">
<h4>Exercise Answers</h3>
<!-- Display normal question answers -->
{% if questions and answers %}
{% for question in questions %}
<h6><b>{{ question.title }}</b></h6>
{% if answers %}
<ol>
{% for answer in answers %}
{% if answer.question.id == question.id %}
<li>{{ answer.answer }}</li>
{% endif %}
{% endfor %}
</ol>
{% endif %}
<h6>Expected Answer</h6>
<p>{{ question.expected_answer|safe }}</p>
<hr/>
{% endfor %}
{% endif %}
<!-- Display multichoice question answers -->
{% if multichoice_questions and mc_answers %}
{% for mc_question in multichoice_questions %}
<h6><b>{{ mc_question.title }}</b></h6>
{% if mc_answers %}
{% for mc_answer in mc_answers %}
{% if mc_answer.question.id == mc_question.id %}
<p>{{ mc_answer.selected_choice }}</p>
{% endif %}
{% endfor %}
{% endif %}
<h6>Expected Answer</h6>
<p>{{ mc_question.expected_answer|safe }}</p>
<hr/>
{% endfor %}
{% endif %}
<!-- Display essay question answers -->
{% if essay_questions and eq_answers %}
{% for es_question in essay_questions %}
<h6><b>{{ es_question.title }}</b></h6>
{% if eq_answers %}
{% for eq_answer in eq_answers %}
{% if eq_answer.question.id == es_question.id %}
<p>{{ eq_answer.answer }}</p>
{% endif %}
{% endfor %}
{% endif %}
<h6>Expected Answer</h6>
<p>{{ es_question.expected_answer|safe }}</p>
<hr/>
{% endfor %}
{% endif %}
<!-- This exercise has not been answered -->
{% if not answers and not mc_answers and not eq_answers %}
<p>Will be revealed after submitting your work.</p>
{% endif %}
<!-- Show next lesson button if available -->
{% if answers or mc_answers or eq_answers %}
{% if lesson.next_lesson %}
<p>
<div class="btn-container btn-container-warning">
<a class="btn btn-warning btn--minimal btn-lg-bordered btn-inverse" href="{% url 'learn_lesson' lesson.next_lesson.module.course.slug lesson.next_lesson.module.slug lesson.next_lesson.slug %}">Next Lesson</a>
</div>
</p>
{% endif %}
{% endif %}
</div>
</div>
</div>
<!-- end tabs -->
Here is the view.py
def lesson_exercise_posted(request, lesson_id, exercise_id):
if request.method == 'POST':
form = LessonExerciseForm(request.POST)
lesson = Lesson.objects.get(pk=lesson_id)
exercise = Exercise.objects.get(pk=exercise_id)
exercise_submission, created = ExerciseSubmission.objects.get_or_create(
student=request.user,
#lesson=lesson,
exercise=exercise)
if created:
for key in request.POST.iterkeys():
value = request.POST.get(key)
print("{0}:::{1}".format(key, value))
if value:
# Get Link Questions; Can be more than one
if key.startswith('qu'):
prefix, question_id, question_counter = key.split('-')
qu_question = Question.objects.get(pk=question_id)
user_answer = UserAnswer(student=request.user,
question=qu_question,
answer=value.strip(),
exercise_submission=exercise_submission)
user_answer.save()
# Get Multichoice Questions
if key.startswith('mcq'):
prefix, question_id, choice_counter = key.split('-')
mc_question = MultiChoiceQuestion.objects.get(pk=question_id)
mc_option_selected = MultiChoiceQuestionOption.objects.get(question=mc_question, content=value.strip())
mc_answer = MultiChoiceUserSubmittedAnswer(
student=request.user,
question=mc_question,
selected_choice=mc_option_selected,
exercise_submission=exercise_submission)
mc_answer.save()
# Get Essay Questions
if key.startswith('eq'):
prefix, question_id = key.split('-')
essay_question = EssayQuestion.objects.get(pk=question_id)
try:
essay_answer = EssayUserAnswer.objects.get(student=request.user, question=essay_question)
except EssayUserAnswer.DoesNotExist:
essay_answer = EssayUserAnswer(student=request.user,
question=essay_question,
answer=value.strip(),
exercise_submission=exercise_submission)
essay_answer.save()
# Update the user progress
progress = StudentLessonProgress.objects.get(student=request.user, lesson=lesson)
progress.status = COMPLETED
progress.done_percent = 100 # Incrementing percentage at this stage to make it 100
progress.save()
messages.success(request, "Thank you! Your answer submission has been saved. Click on the Answers tab to reveal the correct answers.")
else:
form = LessonExerciseForm()
messages.success(request, "Thank you! Your answer submission was NOT saved because you had previously done this exercise.")
return HttpResponseRedirect( '{0}#answers'.format(reverse('learn_lesson',
kwargs={
'form':form,
'course_slug':lesson.module.course.slug,
'module_slug':lesson.module.slug,
'lesson_slug':lesson.slug}
)))
Here is the models.py
class Exercise(models.Model):
title = models.CharField(max_length=256, null=True)
def __unicode__(self):
return self.title
class ExerciseSubmission(models.Model):
""" Data Model representing a student's exercise Submission. """
student = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='The Student', related_name='exercise_submissions')
exercise = models.ForeignKey(Exercise, verbose_name=_("Exercise"))
#lesson = get_model('jm_lms.apps.courses.models', 'Lesson') #models.ForeignKey(Lesson, verbose_name='Lesson')
date = models.DateTimeField(editable=False, auto_now_add=True)
class Meta:
verbose_name = _("Exercise Submission")
verbose_name_plural = _("Exercise Submissions")
class BaseQuestion(models.Model):
exercise = models.ForeignKey(Exercise, verbose_name=_("Exercise"))
title = models.TextField(verbose_name="Topic Box", blank=True, null=True)
expected_answer = models.TextField(verbose_name="Expected Answer", blank=True, null=True, help_text=_("How the learner should answer the question. Shown after the question has been answered."))
class Meta:
abstract = True
def __unicode__(self):
return self.title
class Question(BaseQuestion):
num_of_expected_answers = models.IntegerField(default=1, verbose_name=_("Number of expected answers"))
class Meta:
verbose_name = _("List Question")
verbose_name_plural = _("List Questions")
class UserAnswer(models.Model):
"""
Response given by a user
"""
student = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='The Student', related_name='exercise_answers')
question = models.ForeignKey(Question, verbose_name=_("Question"))
answer = models.CharField(max_length=256, null=True)
answered_on = models.DateTimeField(auto_now_add=True, blank=True, null=True)
exercise_submission = models.ForeignKey(ExerciseSubmission, verbose_name=_("Exercise Submission"), blank=True, null=True)
# status = models.IntegerField(verbose_name="Answer Status", choices=USER_ANSWER_STATUS, default=NOT_PUBLISHED, help_text='Enable user answer reference in the next Lesson')
class Meta:
ordering = ("id",)
verbose_name = _("User Answer to List Question")
verbose_name_plural = _("User Answers to List Question")
def __unicode__(self):
return self.answer
class MultiChoiceQuestion(BaseQuestion):
class Meta:
verbose_name = _("Multiple Choice Question")
verbose_name_plural = _("Multiple Choice Questions")
def check_if_correct(self, guess):
answer = MultiChoiceQuestionOption.objects.get(id=guess)
if answer.correct is True:
return True
else:
return False
def get_answers(self):
return MultiChoiceQuestionOption.objects.filter(question=self)
def get_answers_list(self):
return [(answer.id, answer.content) for answer in MultiChoiceQuestionOption.objects.filter(question=self)]
class MultiChoiceQuestionOption(models.Model):
question = models.ForeignKey(MultiChoiceQuestion, verbose_name=_("Question"))
content = models.CharField(max_length=1000,
blank=False,
help_text=_("Enter the answer text that you want displayed"),
verbose_name=_("Answer Content"))
correct = models.BooleanField(blank=False,
default=False,
help_text=_("Is this a correct answer?"),
verbose_name=_("Correct"))
class Meta:
verbose_name = _("MultiChoice Option")
verbose_name_plural = _("MultiChoice Options")
def __unicode__(self):
return self.content
class MultiChoiceUserSubmittedAnswer(models.Model):
student = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='The Student', related_name='exercise_submitted_choice')
question = models.ForeignKey(MultiChoiceQuestion, verbose_name=_("Question"))
selected_choice = models.ForeignKey(MultiChoiceQuestionOption, verbose_name=_("Question"))
answered_on = models.DateTimeField(auto_now_add=True, blank=True, null=True)
exercise_submission = models.ForeignKey(ExerciseSubmission, verbose_name=_("Exercise Submission"), blank=True, null=True)
# status = models.IntegerField(verbose_name="Answer Status", choices=USER_ANSWER_STATUS, default=NOT_PUBLISHED, help_text='Enable user answer reference in the next Lesson')
class Meta:
verbose_name = _("MultiChoice Submitted User Answer")
verbose_name_plural = _("MultiChoice Submitted User Answers")
def __unicode__(self):
return self.selected_choice.content
class EssayQuestion(BaseQuestion):
class Meta:
verbose_name = _("Essay Question")
verbose_name_plural = _("Essay Questions")
class EssayUserAnswer(models.Model):
student = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='The Student', related_name='exercise_essay_answers')
question = models.ForeignKey(EssayQuestion, verbose_name=_("Question"))
answer = models.TextField(null=True, blank=True)
answered_on = models.DateTimeField(auto_now_add=True, blank=True, null=True)
exercise_submission = models.ForeignKey(ExerciseSubmission, verbose_name=_("Exercise Submission"), blank=True, null=True)
# status = models.IntegerField(verbose_name="Answer Status", choices=USER_ANSWER_STATUS, default=NOT_PUBLISHED, help_text='Enable user answer reference in the next Lesson')
# class TableExerciseQuestion(BaseQuestion):
# class Meta:
# verbose_name = _("Table Exercise Question")
# verbose_name_plural = _("Table Exercise Questions")
#
#
# class TableExercise(models.Model):
# """
# Model to enable lesson developer to add lesson exercise fields headers ,description e.t.c
# """
# question = models.ForeignKey(TableExerciseQuestion, verbose_name=_("Question"))
# field_name = models.CharField(max_length=200)
# field_occurrence = models.IntegerField(default=1, verbose_name=_("Number of expected fields"))
Here is the forms.py
class LessonExerciseForm(forms.ModelForm):
model = [MultiChoiceQuestion, ExerciseSubmission, EssayQuestion]
fields = '__all__'
I had very similar problem while dealing with different issue. But I think your problem is the same.
link to post
Basically the problem was the html code. I would suggest that you verify your generated html code in browser and check if the form tags are closed properly. It might be the case that form tags are closed earlier than your data is coming later in html and it wouldn't be submitted. Check generated html.
Update:
The issue seemed to be in the coding for Django-formset. I was processing it as an inline formset and not a model formset. The answer below was also correct. Thanks!
I am working with a model formset for an intermediate model. I am using django-formset js to add additional formset fields on the template. Most everything works OK except that when I go to save the formset only the first entry is being saved to the DB. The first entry is saved and assigned correctly but any after than just disappear. It is not throwing any errors so I am not sure what is going wrong. Thanks!
The Model
class StaffAssignment(models.Model):
study = models.ForeignKey(Study, related_name='study_set', null=True, on_delete=models.CASCADE)
staff = models.ForeignKey('account.UserProfile', related_name='assigned_to_set', null=True, on_delete=models.CASCADE)
role = models.CharField(max_length=100, null=True)
assigned_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-role',)
def __str__(self):
return '{} is assigned to {}'.format(self.staff, self.study)
The Form:
class AddStaff(forms.ModelForm):
model = StaffAssignment
fields = ('staff',)
def __init__(self, *args, **kwargs):
super(AddStaff, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].widget.attrs.update({'class': 'form-control'})
The View:
def add_staff(request, study_slug):
study = get_object_or_404(Study, slug=study_slug)
staff_formset = modelformset_factory(StaffAssignment, form=AddStaff, fields=('staff',), can_delete=True)
if request.method == 'POST':
staffList = staff_formset(request.POST, request.FILES)
if staffList.is_valid():
for assignment in staffList:
assigned = assignment.save(commit=False)
assigned.study = study
assigned.role = assigned.staff.job_title
assigned.save()
return HttpResponseRedirect(reverse('studies:studydashboard'))
else:
HttpResponse('Something is messed up')
else:
staffList = staff_formset(queryset=StaffAssignment.objects.none())
return render(request, 'studies/addstaff.html', {'staffList': staffList, 'study': study})
The Template:
<form action="{% url 'studies:addstaff' study.slug %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="box-body">
{% for list in staffList %}
<div class="form-group" id="formset">
{% if list.instance.pk %}{{ list.DELETE }}{% endif %}
{{ list.staff }}
{% if list.staff.errors %}
{% for error in list.staff.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
{{ staffList.management_form }}
</div>
<div class="box-footer">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
You are not including the primary key field in the template, as required by the docs. Add
{% for list in staffList %}
{{ list.pk }}
...
{% endfor %}