Passing Form Querystring (custom queryset) to Django Detailview - django

I have a form:
class MyTestForm(forms.Form):
options = (
("1", "deck1"),
("2", "deck2"),
("3", "deck3"),
("4", "deck4"),
)
choices = forms.MultipleChoiceField(choices = options, widget=forms.CheckboxSelectMultiple, required = False)
and a views.py which passes the querystring of the form:
class NewFormView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
form = MyNewForm()
context = {'form':form }
return render(request, 'testformv2.html', context)
def post(self, request, *args, **kwargs):
form = MyNewForm(data=request.POST)
if form.is_valid():
data=form.cleaned_data
base_url = reverse('newcombined', kwargs={'pk':24}) ## change this
querystring = '{}?'.format(base_url)
myqueries = [query for query in data if data[query] != []] # take the non-empty selections of the form
for query in myqueries:
if len(data[query]) == 1:
query_arguement = str(query)+'='+str(data[query][0]) +'&'
querystring += query_arguement
elif len(data[query])>1:
query_argument = str(query)+'='+','.join(data[query])+'&'
querystring += query_argument
else:
print('error occured for some reason')
url = querystring[:-1] #takes the last character & sign off
return redirect(url)
return render(request, 'testformv2.html', {'form':form})
so i will end up with a url that looks like "/v2/test/25/?Decks=2,4" ... my problem is I want to use the querystring filters to filter for a specific queryset, however, i must provide DetailView with a primary key in the URL. I am wondering if i should be processing the queryset in the post request of the form (when the form is submitted), OR if i should get the primary key of one of the objects in the queryset, and THEN get the custom filtered queryset in the DetailView. (my problem is more complicated than this because i have a form on the detailview which uses get_object() function, so i cannot use ListView.

Related

DoesNotExist - matching query does not exist

I have this django class-based view where i am trying to overwrite the get_queryset function because i want get to the inserted values from the frontend to search in my database after the subject with that name and then get the id. but when i call the view it gives me a "Subject matching query does not exist." because the subject_val is None. That makes sense because the user has not submitted the values jet.. so how do i get it to wait until a user have choosen "submit
class AttendanceList(LoginRequiredMixin, ListView):
model = AttendanceLog
template_name = "./attendancecode/showattendance.html"
def get_queryset(self):
class_val = self.request.GET.get('class')
subject_val = self.request.GET.get('subject')
sub = Subject.objects.get(name=subject_val).id
new_context = get_statstic(class_val, sub)
return new_context
def get_context_data(self, **kwargs):
context = super(AttendanceList, self).get_context_data(**kwargs)
context['class'] = self.request.GET.get('class')
context['subject'] = self.request.GET.get('subject')
return context
You can check if the values are not None, in case they are, you need to return another queryset of AttendanceLogs (for example AttendanceLog.objects.all() or AttendanceLog.objects.none()):
class AttendanceList(LoginRequiredMixin, ListView):
model = AttendanceLog
template_name = "./attendancecode/showattendance.html"
def get_queryset(self):
class_val = self.request.GET.get('class')
subject_val = self.request.GET.get('subject')
if class_val is not None and subject_val is not None:
sub = Subject.objects.get(name=subject_val).id
return get_statstic(class_val, sub)
# return another queryset:
return AttendanceLog.objects.none()
# …

Django CBV return different page based on form data

Using CreateView, I am trying to save and return a url based on the items selected in the form. This is for a workout log site where the second form you are directed to is based on the type of workout you want, based on info entered in the first form. I would like to do this without Javascript:
class WorkoutLogCreateView(CreateView):
model = Workout_Log
template_name = 'workout/workout_log_create.html'
fields = ['date_time', 'modality', 'workout_type', 'workout_model']
#something like this:
def get_success_url(self):
if workout_type = '5 rounds'
return reverse('five-rounds-log-create')
elif workout_type = 'Drop Reps'
return reverse('drop-reps-log-create')
else
return reverse('workout-log-menu')
def get_context_data(self, **kwargs):
context = super(WorkoutLogCreateView, self).get_context_data(**kwargs)
context['action'] = reverse('workout-log-create')
return context
In the get_success_url method, you can access the object with self.object.
def get_success_url(self):
if self.object.workout_type = '5 rounds'
return reverse('five-rounds-log-create')
elif self.object.workout_type = 'Drop Reps'
return reverse('drop-reps-log-create')
else
return reverse('workout-log-menu')

django form is invalid, but no error messages

I have the following form:
class SkuForm(forms.Form):
base_item = forms.ModelChoiceField(queryset=BaseItem.objects.none())
color_or_print = forms.ModelMultipleChoiceField(queryset=Color.objects.none())
material = forms.ModelMultipleChoiceField(queryset=Material.objects.none())
size_group = forms.ModelMultipleChoiceField(queryset=Size_Group.objects.none())
my view:
def sku_builder(request):
if request.method == "POST":
user = request.user
form = SkuForm(request.POST)
if form.is_valid():
base_item = form.cleaned_data['base_item']
colors = filter(lambda t: t[0] in form.cleaned_data['color_or_print'], form.fields['color_or_print'].choices)
materials = filter(lambda t: t[0] in form.cleaned_data['material'], form.fields['material'].choices)
size_groups = filter(lambda t: t[0] in form.cleaned_data['size_group'], form.fields['size_group'].choices)
return render(request, 'no_entiendo.html', {'colors': colors, })
else:
return HttpResponse("form is not valid")
user = request.user
form = SkuForm()
form.fields['base_item'].queryset = BaseItem.objects.filter(designer=user)
form.fields['color_or_print'].queryset = Color.objects.filter(designer=user)
form.fields['material'].queryset = Material.objects.filter(designer=user)
form.fields['size_group'].queryset = Size_Group.objects.filter(designer=user)
return render(request, 'Disenador/sku_builder.html', {'form': form,})
The problem is that Im only receiving the "form is not valid message" I have no idea why it is not valid as the Form is only made of choices, so no typo error. Also I have no feedback from the system to debug, or don't know where to search.
*what happens after form.is_valid is not the complete code
UPDATE:
I placed the {{ form.errors}} and got this:
color_or_print
Select a valid choice. 6 is not one of the available choices.
base_item
Select a valid choice. That choice is not one of the available choices.
size_group
Select a valid choice. 2 is not one of the available choices.
In size_group and color_or_print the number is the pk (but is only showing one item, 2 were selected), not sure what is happening in base_item. Should I extract the values through a:
get_object_or_404 ?
and what can I do with base_item? here is an image of the information
posted from the debug_toolbar
Instead of sending an HttpResponse, you need to render the html with the form if the form is invalid.
if form.is_valid():
# Do your operations on the data here
...
return render(request, 'no_entiendo.html', {'colors': colors, })
else:
return render(request, 'Disenador/sku_builder.html', {'form': form,})
Also if you're using model choice fields, the ideal place to define your queryset is in your form's __init__ method
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
self.fields['base_item'].queryset = BaseItem.objects.filter(designer=user)
# define more querysets here as you require
...
super(SkuForm, self).__init__(*args, **kwargs)
You can change the queryset in view. But that as far as I understand is a way to override whatever you have set in your forms. It should normally be set in __init__.
try to render {{form.errors}} in your template

Dynamic initialisation of form in Django

I am trying to initialise a form dynamically. This is my forms.py:
class MapLocalityForm(forms.Form):
def search_locs(self, location):
print("inside form")
print(location)
return Locality.objects.filter(name=location)
def __init__(self,*args, **kwargs):
self.loc = kwargs.pop('loc', None)
super(MapLocalityForm, self).__init__(*args, **kwargs)
self.fields['locality'] = forms.ModelChoiceField(queryset='',widget=forms.RadioSelect(),required=True,
initial=1)
if self.loc:
loc_term = self.loc
# print(loc_term)
loc_list = self.search_locs(loc_term)
# print(loc_list)
self.fields['locality'].queryset = loc_list
else:
self.fields['locality'].queryset = Locality.objects.none()
So I perform a check in views.py:
def map_locality(request,freq_term):
if request.method =='POST':
form = MapLocalityForm(request.POST, loc=freq_term)
if form.is_valid():
"do something"
else:
form = MapLocalityForm()
return render(request, 'maplocalities.html', {'form': form,'loc':freq_term,'alias_created':alias_created})
I am directed to this view using a redirect option, so the request is GET. Whenever I jump to this maplocalities.html, I get an empty form because the code goes to the else part and there are no arguments. Usually when we create a form which is static, a form is displayed when it goes to the else part. Any idea ow can I rectify my view to perform just like static forms.

django variable of one view to another from session

I m very confused on this and I dont have any idea how to do this..
I have a view where I have listed all the news from my news table. To display the news I have passed context data in list view. Here is my view
class SingleNewsView(ListView):
model = News
form_class = SearchForm
template_name = "single_news.html"
# def post(self, request, **kwargs):
# print "request"
# form = SearchForm(request.user)
def get(self, request, pk, **kwargs):
#form = SearchForm(request.user)
self.pk = pk
self.pub_from = request.GET.get('pub_date_from',False)
self.pub_to = request.GET.get('pub_date_to',False)
self.crawlers = request.GET.get('crawler',False)
print self.crawlers
return super(SingleNewsView,self).get(request,pk, **kwargs)
def get_context_data(self, **kwargs):
context = super(SingleNewsView,self).get_context_data(**kwargs)
context["form"] = SearchForm
if self.pub_from and self.pub_to and self.crawlers:
context["something"] = News.objects.filter(category_id=self.pk).filter(published_date__range=(self.pub_from,self.pub_to), crawler=self.crawlers)
else:
context["something"] = News.objects.filter(category_id=self.pk)
return context
and I have written view that I referenced from django doc to download the news in csv format.. I have also included a search form to filter the news. In my first view I have passed context["something"] to display the list of news in the template.
Now what I want is to download that news in csv. I have written a view for this
def CSVView(request):
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename=somefilename.csv"'
some_val = request.session["something"]
print some_val
print "this"
writer = csv.writer(response)
writer.writerow(some_val)
return response
This is my next view to download the csv. Here what I am trying to do is to download the news that come after filter. In my first view context["something "] gives the list of news. I did all but dont know how to get it. Lastly I m trying to get the value of contxt["something"] from session but I am failed in that too. How can I get the value of one view to another. Or anyone have better idea how can I download the news that is returned by context["something"]. What am I doing wrong.
Setting data in context does not put it in session. You need to set data in session to store it there. Also, storing objects directly in session is not a good idea. You may have to serialize them.
Better way would be create list of pks of objects you want into session.
Something like:
def get_context_data(self, **kwargs):
context = super(SingleNewsView,self).get_context_data(**kwargs)
context["form"] = SearchForm
if self.pub_from and self.pub_to and self.crawlers:
qs = News.objects.filter(category_id=self.pk).filter(published_date__range=(self.pub_from,self.pub_to), crawler=self.crawlers)
else:
qs = News.objects.filter(category_id=self.pk)
context["something"] = qs
#set data in session
self.request.session['something_pks'] = [ i.pk for i in qs ]
return context
Then in CSVView you can get them with `request.session['something_pks'] and do the query for objects.