Select a valid choice is not one of the available choices - python

I'm new to Django. What i'm trying to do is to show some JSON response value which i converted into tuples to show in the choicefield of my Django form.
This is how i'm creating the tuples
usernamelist = []
useremaillist = []
for userobject in userobjects:
username = userobject['somevalue']
email = userobject['somevalue']
useremaillist.append(email)
usernamelist.append(username)
user_tuple = zip(usernamelist,useremaillist)
This is my form
class UserSelectForm(forms.Form):
users = forms.ChoiceField(label="Select user")
Then in my views i'm trying to put all these names into drop down list
selectform = UserSelectForm()
selectform.fields['users'].choices = user_tuple
its successfully showing but when i try to submit my form i'm getting Select a valid choice is not one of the available choices error.
This is where i'm trying to get the drop down selected value from submitted form
if request.method == 'POST' and 'preview' in request.POST:
selectform = UserSelectForm(request.POST)
if selectform.is_valid():
user_email = selectform.cleaned_data['users']
print user_email
return HttpResponseRedirect('/')

If you really need to manually decide the choices then you should include them as a requirement for the initializer for the form
class UserSelectForm()
def __init__(self, choices, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['users'].choices = choices
Then call it with the choices
UserSelectForm(user_tuple, request.POST or None)

Related

How To Update Specific Model Field From Django View Before Saving A Form

So, How can I update some Model Fields automatic, without the user having to input the values?
In Models:
class Url(models.Model):
long_url = models.CharField("Long Url",max_length=600)
short_url = models.CharField("Short Url",max_length=7)
visits = models.IntegerField("Site Visits",null=True)
creator = models.ForeignKey(CurtItUser,on_delete=models.CASCADE,null=True)
def __str__(self):
return self.short_url
In Views:
def home(request):
"""Main Page, Random Code Gen, Appendage Of New Data To The DB"""
global res,final_url
if request.method == 'POST':
form = UrlForm(request.POST)
if form.is_valid():
res = "".join(random.choices(string.ascii_uppercase,k=7))
final_url = f"127.0.0.1:8000/link/{res}"
form.save()
redirect(...)
else:
form = UrlForm
return render(...)
Sow how can for exapmle set from my view the value of short_url to final_url ???
You can get the data you need from the form.
you need to get the specific instance first, then you can use that instance to save values from the form.
And do not forget to save!
url_instance = get_object_or_404(Url, pk=pk)
url_instance.short_url = form.cleaned_data['short_url']
url_instance.long_url = form.cleaned_data['long_url']
url_instance.visits = form.cleaned_data['visits']
url_instance.save()
You can find more detailed infromations in the Django Documentation.

Save data from ChoiceField to database Django

I'm new to Django and I have built a Form that shows a single select field to chose from. The data in the field are calculated on the go by the Form.
I now need, once the data is being submitted, to be save on the database. The only problem is that, for some reason, I got an IntegrityError error NOT NULL constraint failed: manager_playlist.user_id
Below my view, form and model in Django
views.py
def playlist(request):
if not is_user_already_auth_spotify(request):
messages.error(request, "You're not authenticated with Spotify, please authenticate here")
return redirect('/members/account/' + request.user.username)
if request.method == "POST":
form = ChoosePlaylistForm(request.POST, request=request)
if form.is_valid():
form.save()
messages.success(request, "Playlist successfully chosen")
return HttpResponseRedirect('account')
else:
pass
else:
form = ChoosePlaylistForm(request=request)
return render(request, 'show_playlist.html', {"playlist_choose_form": form})
forms.py
class ChoosePlaylistForm(ModelForm):
playlists = forms.ChoiceField(choices=())
class Meta:
model = Playlist
fields = ('playlists',)
def __init__(self, *args, request=None, **kwargs):
super(ChoosePlaylistForm, self).__init__(*args, **kwargs)
self.request = request
self.fields['playlists'].choices = self.generate_selection()
def generate_selection(self):
sp_auth, cache_handler = spotify_oauth2(self.request)
spotify = spotipy.Spotify(oauth_manager=sp_auth)
s_user = spotify.current_user()
u_playlists = spotify.user_playlists(s_user['id'], limit=10)
choices = []
for playlist in u_playlists["items"]:
if playlist["owner"]["id"] == s_user['id']:
playlist_choice = (playlist["id"], playlist["name"])
choices.append(playlist_choice)
else:
pass
return choices
model.py
class Playlist(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
playlists = models.CharField(max_length=50, null=True, blank=True) # playlists are the ids of the playlists
def __str__(self):
return self.playlists
The reason for the error is that when a new Playlist object is created, the user field must not be empty (you did not add null=True, and of course, would not make sense here if you did). Now the form validates because the form does not require the user field, only the playlists field. You have a couple of choices.
Option 1
Add the required field to your form (I haven't tested this, please check the docs!):
class ChoosePlaylistForm(ModelForm):
playlists = forms.ChoiceField(choices=())
class Meta:
model = Playlist
fields = ('playlists', 'user',) # NOTE THE CHANGE HERE
def __init__(self, *args, request=None, **kwargs):
super(ChoosePlaylistForm, self).__init__(*args, **kwargs)
self.request = request
self.user = request.user # Add the user to the form
Option 2
Save the form as is using commit=False, then add the missing field before you save your model:
if request.method == "POST":
form = ChoosePlaylistForm(request.POST, request=request)
if form.is_valid():
playlist = form.save(commit=False) # NOTE THE CHANGE HERE
playlist.user = request.user # Add the user to the partial playlist
playlist.save() # Now you can save the playlist
messages.success(request, "Playlist successfully chosen")
return HttpResponseRedirect('account')
Option 3
Add the field when you instantiate the form itself (I'm not sure my syntax is correct here):
form = ChoosePlaylistForm(request.POST, request=request, instance=request.user)
EDIT
Option 3 above does not seem to work. I believe this edit will:
form = ChoosePlaylistForm(request.POST, request=request, initial={'user': request.user})

Django Form Error: Select a valid choice. ... is not one of the available choices

I am trying to create a dynamic choice field. I have a view that creates a list of tuples. The first value of the tuple is the primary key of the object ServiceWriter while the second value is the name of the ServiceWriter. The list then gets passed into the form class. When I make the selection and submit the page the form is decided to be not valid and the following form error is printed in the shell: "Select a valid choice. (First value of tuple. ie 1,2,3..) is not one of the available choices."
forms.py
class CreateAdvancedRO(forms.Form):
service_writer = forms.ChoiceField()
def __init__(self, writer_choices, *args, **kwargs):
super(CreateAdvancedRO, self).__init__(*args, **kwargs)
self.fields['service_writer'].choices = writer_choices
self.helper = FormHelper()
self.helper.form_id = 'id-create-advanced-ro'
self.helper.form_method = 'post'
self.helper.add_input(Submit('submit', 'Open Repair Order'))
Note: I am not using a ModelForm.
views.py
class CreateAdvancedRO(View):
form_class = CreateAdvancedRO
writer_form = CreateServiceWriter
add_line_form = AddJobLine
def post(self, request):
writer_choices = []
form = self.form_class(writer_choices, request.POST)
print(form.errors)
if form.is_valid():
'''Do something'''
else:
writer_choices = []
try:
writers = ServiceWriter.objects.filter(user=request.user)
for writer in writers:
writer_choices.append((str(writer.id), writer.name))
except ObjectDoesNotExist:
pass
form = self.form_class(writer_choices, request.POST)
writer_form = self.writer_form()
add_line_form = self.add_line_form()
return render(request, 'free/advanced_create.html', {'form': form, 'writer_form': wri
'add_line_form': add_line_form})
I have tried both of the following in the view:
writer_choices.append((str(writer.id), writer.name)) and
writer_choices.append((writer.id, writer.name))
Here is the ServiceWriter model, just in case.
class ServiceWriter(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=20, blank=False)
def __str__(self):
return str(self.name)
Any thoughts?
Thanks for the help.
It looks like you're trying to validate the form against an empty list of choices. Have you tried populating writer_choices before instantiating or attempting to validate the form?

django - load currently logged in user information in the form

django noob here.
The question i am going to ask has been asked several times, however, i couldn't find the answers which can help my case.
the query is:
I have a Form having a choice field which loads its choices information from the database. Basically, I have designed my models in such a way that, the choices displayed is individual to the users.
for example:
for user1, the choice field shows a,b,c,d.
where as for user 2, the choice field shows v,w,d.
The problem i am facing is referencing the logged in user and getting the username. then pass the username as the filter to the database.
I have come across numerous init functions trying to do this, somehow it is not helping my case.
forms.py
class class_model(forms.Form):
class_name = forms.ChoiceField(
required=False,
widget=forms.Select,
)
def __init__(self, user, *args, **kwargs):
self.user = user
super (class_model, self).__init__(*args, **kwargs)
current_user = self.user
name = current_user.username
k = User.objects.get(username=name)
y = UserProfile.objects.get(user=k)
schoolid = y.schoolid
primary_filter = Class1.objects.filter (school_id=schoolid)
ax = [("Choose Class", "Choose Class")] + list (primary_filter.objects.values_list ('class_name', 'class_name').distinct())
self.fields['class_name'].choices = ax
The error i receive: 'QueryDict' object has no attribute 'username'
Update:
views.py
#login_required(login_url="login/")
def create(request):
print(request.method)
if request.method == 'POST':
form2 = class_model(request.POST, request.user)
if form2.is_valid():
class_name = form2.cleaned_data['class_name']
return render(request, 'create_student.html', {'form2': form2}
else:
print(form.errors)
return render(request, 'create_student.html', {'form2': form2})
You've told the form to expect the user as the first positional parameter, so you need to pass it there.
form2 = class_model(request.user, data=request.POST)

Preserve checked checkboxes after post in django

I want to keep the form fields preserved after submitting the form. I can preserve all the fields except the checked checkboxes
Here is my form action view:
def student_submit_info(request):
form_values = {}
if request.method == 'POST':
form = StudentForm(request.POST)
print form.is_valid()
form_values = getDetails(request)
if form.is_valid():
print request.user.username
student = Student.objects.get(user=request.user)
// saving student to DB
saveDetails(request, student, form_values)
return render_to_response('student.html', form_values, context_instance=RequestContext(request))
def getDetails(request):
#fetch input data
form_values = {}
form_values['first_name'] = request.POST['first_name']
form_values['last_name'] = request.POST['last_name']
form_values['skills'] = request.POST.getlist('skills[]')
return form_values
I would want to preserve skills (checkbox), here's a part of my template
skill1<input type="checkbox" name="skills[]" checked value="skill1"/>
skill2<input type="checkbox" name="skills[]" value="skill2"/>
skill3<input type="checkbox" name="skills[]" value="skill3"/>
You should make a custom django Forms to handle easily forms, example of a post view:
def post_view(request):
form = MyForm(request.POST)
if form.is_valid():
do_something()
render(request, 'your_temp', {'MyForm': MyForm'})
With this kind of snippet, data in form will always be those sent.
You can override is_valid() for empty skill checkboxes.
Perhaps, use CBV's and ModelForms to make the process simpler.
Combine a listview (or similar) and add your form via context.
Then in get_context_data of your CBV:
form_values = {}
#Simpler code below for accessing post dictionary
for key, value in self.request.POST.items():
if value == 'on':
form_values[key] = value
context = super().get_context_data(**kwargs)
# You need to add form_values to make it accessible in the forms.py
context['form'] = YourFormName(form_values)
Then, in your forms.py (I'm hoping you use modelforms):
def __init__(self, filters, *args, **kwargs):
super(YourFormName, self).__init__(*args, **kwargs)
if len(form_values) > 0:
for field_name in self.fields:
if field_name in filters:
self.fields[field_name].widget = forms.CheckboxInput(attrs={'checked': True})
I hope this helps.

Categories