I got 2 pages. Step 2 and Step 3. What I'm trying to do is pass the selected object from the step 2 form, to the step 3 form so I can filter the objects of the Step 3 forms. You can see the 2 pages/forms in the images below. So when a user selects a university in step 2, then the step 3 must show only the courses of the selected university.
My current code is really simple since I'm deleting and re-writing the code for the past days without results.
views.py
def step2(request):
universities = University.objects.order_by('name').distinct()
return render_to_response("registration/step2.html", {'universities': universities}, RequestContext(request))
def step3(request):
courses = Course.objects.order_by('name')
return render_to_response("registration/step3.html", {'courses': courses}, RequestContext(request))
In your view, you have to retrieve the selection that the user made and use it to filter the choices for the next form. Something like:
form = FirstForm(request.POST)
if form.is_valid():
uni = form.cleaned_data['uni']
courses = Course.objects.filter(university__name=uni).order_by('name')
return render_to_response("registration/step3.html", {'courses': courses}, RequestContext(request))
Related
I am new to Django Class Based Views and I am working on a project where on the template I want to have Form for creating customer accounts on the left and list of existing customers on the right.
So far I have the list of existing customers displayed but for the form I don't know how to pass its variable context to the same template, or it is not possible to Pass a Form that would be submitted inside a ListView Method. And I also want to generate unique account numbers of 10 Digits in ModelForm which I want the form field to be auto-filled and disabled
Here is my form code:
import secrets
#I want to Generate Account Number of 10 Digits but getting only 2
account = secrets.randbits(7)
#class for Customer Account Form
class CustomerAccountForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().init(*args, **kwargs)
self.fields['accountnumber'].initial = account
class Meta:
model = Customer
fields = ['accountnumber','surname','othernames','address','phone']
Code for my views (ListView)
class CustomerListView(ListView):
model = Customer
form_class = CustomerAccountForm
template_name = 'dashboard/customers.html'
#Function to get context data from queries
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)
#Get Day of today from current date and time
now = datetime.datetime.now()
#Get the date today
date_today = datetime.datetime.now().date
#Count Number of Withdrawals Today and passing in context
context_data['count_withdrawals_today'] = Witdrawal.objects.filter(date__year=now.year, date__month=now.month, date__day=now.day).count()
context_data['count_deposits_today'] = Deposit.objects.filter(date__year=now.year, date__month=now.month, date__day=now.day).count()
context_data['count_accounts'] = Customer.objects.count()
context_data['count_users'] = User.objects.count()
#Calculate today Deposit Today
context_data['total_deposit']= Deposit.objects.filter(date__year=now.year, date__month=now.month, date__day=now.day).aggregate(total_deposit=Sum('deposit_amount')).get('total_deposit') or 0
#Calculate today Withdrawal Today
context_data['total_withdrawal']= Witdrawal.objects.filter(date__year=now.year, date__month=now.month, date__day=now.day).aggregate(total_withdrawal=Sum('withdrawal_amount')).get('total_withdrawal') or 0
return context_data
Someone should please help me on how this is properly done and the form would be submitted successfully. Thanks in anticipation for your answer.
secrets.randbits(k) generates a random integer within a bit range.
For k=4 then Unsigned integer From 0 to 15.
For k=8 then Unsigned integer From 0 to 255.
For k=16 then Unsigned integer From 0 to 65,535, and so on.
If you want 10 random digits then you can use for example:
import random
account = "".join(str(random.randint(0, 9)) for _ in range(10))
After going through many tutorials and blogs on Django Class Based Views with ListViews for Forms, I discovered that ListViews was designed to populate Model items while FormViews is designed for creating and processing forms both can't be used on one template. Although many developers have had a way around it with the use of Multiple Mixins but no best practice has be mentioned for or against their findings yet.
In these case, I concluded that for a Django Template to be able to process Model Form and at the same time Populate Database items, it needs not to use Class Based Views but Function Based Views.
Let's say I have the following html page:
LIVE CODE
Let's say that in each row there is a form (I have to implement it), How can I do so that when I click on 'save' button (also to be implemented) all the inputs of each row are sent in the request.POST and I can process them individually in the backend.
This is my view for a new expense:
def new_expense(request):
data = {
'title': "New Expense",
}
data['projects'] = Project.objects.filter(is_visible=True).values('id')
data['expense_category'] = dict((y, x) for x, y in EXPENSE_CATEGORY)
data['expense_type'] = dict((y, x) for x, y in EXPENSE_TYPE)
form = ExpenseForm()
if request.method == "POST":
reset = request.POST['reset']
form = ExpenseForm(request.POST)
if form.is_valid():
form.save()
if reset == 'true':
form = ExpenseForm()
data['form'] = form
return render(request, "expense/new_expense.html", data)
I would like to create a similar view for multiple new expense creation.
One approach to this problem can be handling each row individually. You can use a very simple and effective tool called django_htmx for this task. Here is a nice article about how to handle formsets (like) rows: Build dynamic forms with Htmx. Your case seems to be a very good candidate for the example in this article.
I've gone through similar questions but was not able to find a solution to my question. I have 4 cards(movie cards) and the first two are working well but the rest are not. The problem started appearing once I added some logic to views.py in order to show an average rating of each movie based on the reviews given.
Here is the code in views.py
def detail(request, id):
movie = Movie.objects.get(id=id)
reviews = Review.objects.filter(movie=id).order_by('-comment')
average = reviews.aggregate(Avg('rating'))["rating__avg"]
average = round(average, 1)
# The problem is above(in round) but dunno how to fix it
context = {'movie': movie, 'reviews': reviews, 'average': average}
return render(request, 'detail.html', context)
I've got simple project, that do almost nothing now - there is MultipleChoiceField with some Person-values and when user selects some values and clicks "submit" button - I'm sarching for Houses, where selected guys lived.
There is about 1.5k persons and 20k houses in my database. If I select 3+ people from list (in this case, there is about 5-6k values in 'houses' list), processing time is taking very long time (~5-7 seconds for my 't' variable).
As django-debug-toolbar says, DB-queries takes only 0.7 seconds and ~95% of time is 'request' section of 'Timer' panel. So the question is - what am I doing wrong? I think there is wrong way of using render_to_response. Can you recommend me something to optimize my code? I'm new at Django, thank you.
At my 'guess_houses.html' I only display list of houses with their field.
Here is my views.py:
class HouseView(FormView):
template_name = 'guess_houses.html'
form_class = PersonListForm # that's my MultipleChoiceField with persons in it
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
persons_id = form.cleaned_data['persons']
houses= []
t1 = time()
for id_person_dict in House.objects.all().values('id', 'persons', 'address'):
# if persons_id and persons who lived in house got intersection element(s)
if set(persons_id) & set(id_person_dict['persons']):
if id_person_dict not in houses:
houses.append(id_person_dict)
return render_to_response(self.template_name, {'form': form, 'houses': houses, 't': time()-t1})
I am trying to create a SessionWizardView for a trip creation process. The trip might have one leg (one way) or two legs (round trip). Each leg has similar schema so I would like to use the same Form for both step 0 and step1, with a condition saying only to use step1 when the flight is round trip.
The problem I am having is that my "submit" button keeps loading step 0 over and over again instead of moving on to step 1 as it should for a round trip flight. (I am prepopulating each of the forms based on previously requested trip info for each leg in the get_form_initial() override). My form populates correctly for the first leg, it just populates the first leg data on every submit ad infinitum.
I could make two identical forms, but that seems like poor practice. Slightly better, I could have the Return trip form just inherit from the Outbound trip form and not make any changes to it - this is what I'll try next barring a better solution.
But, I'm really wondering if there is there a way to use the same form twice?
In my urls.py:
wizard_forms = [TripCreationForm,TripCreationForm]
urlpatterns = patterns('',
url(r'^trip/wizard/(?P<pk>\d+)$',
views.CreateTripSetView.as_view(wizard_forms,
condition_dict= {'1':show_return_trip_form}), name='admin_add_tripset')
)
in views.py:
def show_return_trip_form(wizard):
"""
Tells the CreateTripSetView wizard whether to show the return trip form
Args:
wizard:
Returns: True if this is a round trip, false if one-way
"""
cleaned_data = wizard.get_cleaned_data_for_step('0') or {}
if cleaned_data.get('total_legs') == 2:
return True
return False
class CreateTripSetView(SessionWizardView):
def get_form_initial(self, step):
"""
Populates the initial form data based on the request, route etc.
THIS IS ALWAYS FIRING FOR STEP=0 WHEN I HIT SUBMIT.
Args:
step:
Returns:
"""
initial = self.initial_dict.get(step, {})
triprequest = TripRequest.objects.filter(id=self.kwargs['pk']).first()
if triprequest is None:
return initial
initial.update({
'request_id': flight_request.id,
#other fields set on initial here
})
return initial
in forms.py:
class TripCreationForm
#field defs ex.
request_id = forms.IntegerField()
#etc.
def __init__(self, initial, *args, **kwargs):
object_data = {}
object_data['request_id'] = initial['request_id']
#etc.
super(AnywhereFlightCreationForm, self).__init__(initial=object_data, *args, **kwargs)
Edited:
So far I've been able to make this work using two subclasses of TripCreationForm but not using TripCreationForm for both.
Thanks in advance!
The wizard needs to identify them as separate steps. Maybe this would work?
wizard_forms = [
("form1", TripCreationForm),
("form2", TripCreationForm),
]