I'm a learner in Python and Django.
I am trying to pass selected checkboxes to my views and then make a get() call to fetch related objects, but keep getting the error DoesNotExist, even though the object is present in the database.
I tried changing the get() parameters but it still shows the same error, as if it just cannot fetch the database. Please help!
ERROR IS IN THE #ed LINE
Here is my views.py
def manage(request):
if request.POST.get('taskname'):
name = request.POST.get('taskname')
end = request.POST.get('enddate')
emp = User.objects.get(username = request.user.username)
print emp.username
try:
newtask = Task(taskname = name, deadline = end, status = 'incomplete', empid = emp)
newtask.save()
except:
print "not saved"
my_tasks = Task.objects.filter(empid = emp)
return render(request, 'ellipse/dashboard.html', {'employee': emp, 'tasks': my_tasks})
else:
selected = request.POST.get('dropdown')
if selected == 'Delete':
tasks = request.POST.getlist('t')
emp = User.objects.get(username = request.user.username)
for seltask in tasks:
#deltask = Task.objects.get(taskname=seltask)
deltask.delete()
my_tasks = Task.objects.filter(empid = emp)
return render(request, 'ellipse/dashboard.html', {'employee': emp, 'tasks': my_tasks})
And, my html:
<div>
<form action="/ellipse/manage/" method="post">
{% csrf_token %}
<p>Taskname <input type="text" name="taskname"></p>
<p>Deadline <input type="date" name="enddate"></p>
<select name="dropdown">
<option selected="selected" disabled>Select action :</option>
<option value="Add">Add</option>
<option value="Delete">Delete</option>
<option value="Mark as complete">Mark as complete</option>
<option value="Mark as incomplete">Mark as incomplete</option>
</select>
{% if tasks %}
{% for tasko in tasks %}
<p><tr><td><input type="checkbox" name="t" value={{ tasko.taskname }}/></td><td>{{ tasko.taskname }}</td><td>{{ tasko.deadline }}</td><td>{{ tasko.status }}</td></tr></p>
{% endfor %}
{% endif %}
<p><button type="submit" name="modify">Modify</button></p>
</form>
</div>
I am clueless on how to proceed further and it'd be great help if this issue can be resolved. Thanks in advance!
Well your get looks jacked up.
emp = User.objects.get(username = request.user.username)
should probably be something like this.
emp = User.objects.get(id=request.user.id)
You could probably do this to...
emp = User.objects.get(user=request.user)
Related
Hey I got this Code to remove my keys:
class AKeysRemove(DeleteView, ProgramContextMixin):
model = AKeys
template_name = 'administration/keys/remove.html'
def dispatch(self, request, *args, **kwargs):
return super(AKeysRemove, self).dispatch(request, *args, **kwargs)
def get_success_url(self):
return reverse('akeys_index', args=[self.get_program_id()])
def delete(self, request, *args, **kwargs):
# Get the query parameters from the request
is_active = request.GET.get('is_active')
category = request.GET.get('category')
# Build a Q object to filter AccessKeys by is_active and category
q_filter = Q()
if is_active is not None:
q_filter &= Q(is_active=is_active)
if category is not None:
q_filter &= Q(category=category)
# Check if there are any filters
has_filters = is_active is not None or category is not None
# Delete the AKeys that match the filter, or just the one AKey
if has_filters:
queryset = self.get_queryset().filter(q_filter)
deleted_count, _ = queryset.delete()
if deleted_count == 1:
messages.success(request, f"One AKey deleted.")
else:
messages.success(request, f"{deleted_count} AKeys deleted.")
else:
obj = self.get_object()
obj.delete()
messages.success(request, f"AKey {obj} deleted.")
return redirect(self.get_success_url())
My url looks like this:
re_path(r'^p/(?P<p_id>[0-9]+)/keys/(?P<pk>[0-9]+)/delete/?$', AKeysRemove.as_view(), name='akeys_delete'),
Deleting one Single Key works fine, but I build myself a filter to delete Keys from a certain category or if they're active or not (is_active)
<div class="row" style="margin-top: 10px">
<div class="col-md-12">
<form method="POST" action="{% url 'akeys_delete' p.id %}" id="delete-akeys-form">
<div class="form-group">
<label for="category-filter">Category:</label>
<select name="category" id="category-filter" class="form-control">
<option value="">All</option>
{% for category in acategories %}
<option value="{{ category.name }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="active-filter">Status:</label>
<select name="is_active" id="active-filter" class="form-control">
<option value="">All</option>
<option value="true">Active</option>
<option value="false">Inactive</option>
</select>
</div>
<button type="submit" class="btn btn-default">Delete</button>
</form>
</div>
</div>
The problem now is that when I open my site I get the obvious error:
Reverse for 'akeys_delete' with arguments '(3,)' not found. 1 pattern(s) tried: ['admin/p/(?P<p_id>[0-9]+)/keys/(?P<pk>[0-9]+)/delete/?$']
Which I understand, since its missing the key.pk, I just can't really figure out how I could re-write my code to accept both single objects to delete and multiple?
I'm thankful for any help :)
I assume you want to support multiple functionality with same view. In that case, why not write two urls pointing to the same view, like this:
re_path(r'^p/(?P<p_id>[0-9]+)/keys/(?P<pk>[0-9]+)/delete/?$', AKeysRemove.as_view(), name='akeys_delete'),
re_path(r'^p/(?P<p_id>[0-9]+)/keys/delete/?$', AKeysRemove.as_view(), name='akeys_multi_delete'),
And update the url in template:
<form method="POST" action="{% url 'akeys_multi_delete' p.id %}" id="delete-akeys-form">
I am trying to make a html dropdown and pass the values into Postgrase SQL database. My dropdown values are being retrieved from another database table. It gives me a MultiValueKeyDictError every time I submit the form. I know I can use forms.py to do the same thing but I want to explore the HTML way of doing this.
My HTML file
<form action = "" method = "post">
{% csrf_token %}
<label for = "LogType"></label>
<input id ="LogType" type = "text" value = "{{ user.department }}">
<label for ="DelayCategory">Delay Category</label>
<select id = "delaycategory" class = "form-control">
{%if user.department == 'TechAssembly'%}
{%for techdelay in techdelay%}
<option value = "{{ techdelay.DelayCode }}">{{ techdelay.DelayCategory}}</option>
{%endfor%}
{%endif%}
{%if user.department == 'Testing'%}
{%for testdelay in testdelay%}
<option value = "{{ testdelay.DelayCode }}">{{ testdelay.DelayCategory}}</option>
{%endfor%}
{%endif%}
</select>
<label for = "iterations">Iterations</label>
<input type = "number" id = "iterations">
<center><input type="submit" value=Submit id = "button"></center>
</form>
My Views.py file
def rulesView(request, user_name):
testdelay = TestingDelayCategory.objects.all()
techdelay = TechDelayCategory.objects.all()
if request.method == "POST":
rulesnew = rules()
rulesnew.DelayCategory = request.GET['DelayCategory']
rulesnew.LogType = request.POST('LogType')
rulesnew.iterations = request.POST('iterations')
rulesnew.save()
context = {
'techdelay':techdelay,
'testdelay':testdelay,
}
return render(request, 'rules/rules.html', context)
rulesnew.DelayCategory = request.GET['DelayCategory']
rulesnew.LogType = request.POST('LogType')
rulesnew.iterations = request.POST('iterations')
Have a second look at this: request.GET should be request.POST and request.POST('LogType') should be request.POST['LogType'] same with iterations.
The error message should include the exact line where the errors was raised. So it would have been way easier to debug if you have told us that the error was raised e.g. in this line rulesnew.LogType = request.POST('LogType')
I wrote codes, but I don't know how to set 'name' and 'value' of hidden tag with Django template. I read Django's Widgets Docs, but I couldn't find the way.
(Pdb) print(errors)
<ul class="errorlist"><li>friend_id<ul class="errorlist"><li>This field is required.</li></ul></li><li>add_remove<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
First, I tried to write like
<input type="hidden" name="friend_id" value="{{ user_info.user_id }}">
and
friend_id = request.POST.friend_id
But I couldn't get how to get POST values without Django's Form. So, I used Django's Form with following codes.
views.py
from myapp.forms import HiddenUserPage
hiddenform = HiddenUserPage
if request.method == 'POST':
hidden = hiddenform(request.POST)
if hidden.is_valid():
from myapp.models import Friends
try:
friend_id = hidden.cleaned_data['friend_id']
add_remove = hidden.cleaned_data['add_remove']
if add_remove == "add":
f = Friends(user_id=request.user.user_id, friend_id=friend_id)
f.save()
elif add_remove == "remove":
f = Friends.objects.filter(user_id=request.user.user_id).get(friend_id=friend_id)
f.delete()
except:
errors = "DB error"
else:
errors = hidden.errors
else:
hidden = hiddenform()
errors = ""
view = {
'errors': errors,
'hidden': hidden,
}
template = 'myapp/user/user_page.html'
return render(request, template, view)
forms.py
class HiddenUserPage(forms.Form):
friend_id = forms.CharField(widget=forms.HiddenInput())
add_remove = forms.CharField(widget=forms.HiddenInput())
user_page.html
<form method="POST" action="" class="">
{% csrf_token %}
<p class="submit">
<button class="confirmbutton" type="submit">
{% if is_friend %}
remove friend
<!-- # I'd like to write like # -->
<!-- <input type="hidden" name="friend_id" value="remove"> # -->
<!-- <input type="hidden" name="friend_id" value="{{ user_info.user_id }}"> # -->
{{ hidden.add_remove }}
{{ hidden.friend_id }}
{% else %}
add friend
<!-- <input type="hidden" name="friend_id" value="add"> # -->
<!-- <input type="hidden" name="friend_id" value="{{ user_info.user_id }}"> # -->
{{ hidden.add_remove }}
{{ hidden.friend_id }}
{% endif %}
</button>
</p>
</form>
Sorry, my code is filthy.
Looks like the question is in providing initial data to the form, then it's is generally done in the view passing initial to the form instantiation, e.g.:
# In your view.py
def ...(...):
# Inside your view function
if request.method == 'GET':
# Provide initial data to the form here
# Get your 'user_info' from models or sessions,
# or wherever you keep it
hidden = hiddenform(initial={"friend_id":user_info.user_id})
if reuest.method == 'POST':
hidden = hiddenform(request.POST)
# Process posted form data
...
# More code general for both HTTP verbs
view = {'errors': errors, 'hidden': hidden}
template = 'myapp/user/user_page.html'
return render(request, template, view)
You might also want to bound the form to model data directly, see the docs for more info.
I've two dropdown menus in one single template. They both are using the same form. But for some reason only one of the form works and gives me MultiValueDictKeyErrorin the views. It gives me error on the line request.session["genderselect"] = request.POST['genderselect']
So I've commented out the lines to see what happens and the code works and shows the first dropdown (name = selection). But the second dropdown of (name = genderselect) doesn't work, although they both are part of the same form.
views.py
def doclistings(request):
d = getVariables(request)
if request.method == "POST":
form = DropdownSelectionForm(request.POST)
if form.is_valid():
print form.errors
selection = form.cleaned_data['selection']
# genderselect = form.cleaned_data['genderselect']
# request.session["genderselect"] = request.POST['genderselect']
request.session["selection"] = request.POST['selection']
return HttpResponseRedirect('/doclistings')
else:
form = DropdownSelectionForm()
# d['genderselect'] = genderselect
s_name = request.session.get('selection')
d['userselection'] = s_name
spec = Specialization.objects.get(name=s_name)
doctors = Doctor.objects.filter(specialization = spec).order_by('-likes')
d['doctors'] = doctors
d.update({'form': form})
return render_to_response('meddy1/doclistings.html',d)
forms.py
class DropdownSelectionForm(forms.Form):
selection = forms.ChoiceField(choices=MY_CHOICES, widget = forms.Select, required = False)
genderselect = forms.ChoiceField(choices=GENDER_CHOICES, widget= forms.Select, required = False)
here is the template where I've the two dropdown
<select class="form-control" id="selection" name="selection">
<option><b>Find a Doctor...</b></option>
{% for value, text in form.selection.field.choices %}
<option value="{{ value }}">{{ text }}</option>
{% endfor %}
</select>
<select class="form-control" id="genderdropdown" name="genderdropdown">
<option><b>Select a Gender</b></option>
{% for value, text in form.genderselect.field.choices %}
<option value="{{ value }}">{{ text }}</option>
{% endfor %}
</select>
<span class="input-group-btn">
<button class="btn btn-primary" type="submit" name="submit" id="ss-submit">Search</button>
</span>
</div>
{% csrf_token %}
</form>
You should change the name="genderdropdown" attribute to match the form field name.
In other words, replace name="genderdropdown" with name="genderselect".
First of all, I am generically creating my form from the database. Here are my codes:
template:
{% block wizard_form_content %}
<div id="alt-list">
<div id="alt-list-header">
<h4>Grids List</h4>
</div>
<div id="alt-list-data" class="container">
{% for grid in data.grids %}
<input type="checkbox" name="{{ grid.name }}" id="id_{{ grid.name }}" tabindex="{{ forloop.counter}}" size="30">{{ grid.name }}<br>
{% endfor %}
</div>
</div>
{% if wizard.form.errors %}
<div class="form-errors-wrapper">
<div class="error">
{% for error in wizard.form.non_field_errors %}
<p>{{ error }}</p>
{% endfor %}
</div>
</div>
{% endif %}
<input type="hidden" name="num-grids" value="{{ data.grids|length }}" id="num-grids" />
<input type="hidden" name="user" value="{{ data.user }}" id="user" />
{% endblock wizard_form_content %}
And this is the corresponding form:
class WhichGridsForm(forms.Form):
# Override the initialize in order to dynamically add fields to the form in order to be saved,
# the fields are saved only when the user selects 'Next Step'.
def __init__(self, *args, **kwargs):
super(WhichGridsForm, self).__init__(*args, **kwargs)
if len(self.data) > 0:
self.num_grids = self.data['num-grids']
user_name = self.data['user']
user1 = User.objects.filter(username=user_name)
gridtype = Grid.GridType.USER_GRID
templateData = ShowGridsData()
templateData.grids = Grid.objects.filter(user=user1, grid_type=gridtype)
for grid in templateData.grids:
gridName = grid.name
# Every time, alternative fields are added with the name 'alternative..', and this because django
# always adds '1-' % (where 1 the number of the step with zero index) prefix in the name,
# with this the names are kept always the same.
self.fields[gridName] = forms.BooleanField(required=False)
Keeping in the mind that this is step 2, when I am trying to reach this step 2 data from step 3 with this line of code:
elif self.steps.step1 == 3:
try:
grids_data = self.get_cleaned_data_for_step('1')
print grids_data
All of the fields seems "False" even though I checked them all.
{u'Cars': False, u'grid11': False, u'deneme11': False, u'asd': False}
Do you have any idea why this would happen?
Edit:
But If I print the form fields in the 'done' method, I get the correct results:
<MultiValueDict: {u'num-grids': [u'4'], u'deneme11': [u'on'], u'Cars': [u'on'], u'composite_wizard-current_step': [u'1'], u'grid11': [u'on'], u'user': [u'muratayan'], u'asd': [u'on'], u'csrfmiddlewaretoken': [u'JYIT5gHs35ZBvk7rCITfpMIPrFleUYXF']}>
Sorry I gave you the wrong field class. Instead MultipleChoiceField it should be ModelMultipleChoiceField, since you select from models.
Something like this works in my case:
forms.py (form for first step)
class FirstStepForm(forms.Form):
def __init__(self, *args, **kwargs):
super(FirstStepForm, self).__init__(*args, **kwargs)
self.fields['countries'] = forms.ModelMultipleChoiceField(queryset=Country.objects.all())
views.py
class MyWizard(SessionWizardView):
def render(self, form=None, **kwargs):
response = super(MyWizard, self).render(form, **kwargs)
grids_data = self.get_cleaned_data_for_step('0') or {}
print grids_data
return response