Django: Sort Items in Dropdown (via field_order?) - django

I am using a dropdown on a template. I do want an alphabetical order in that dropdown and don't know how to get this.
template.html:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
{{ form|crispy }}
</fieldset>
<div>
<button type="submit">OK</button>
</div>
</form>
The context comes from views.py:
def my_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
…
return render(request, 'xxx/template.html', {'form': form})
The form is defined in forms.py:
from django import forms
from .models import Project
class MyForm(forms.Form):
project = forms.ModelChoiceField(queryset=Project.objects)
field_order = ['name', ]
models.py:
class Project(models.Model):
name = models.CharField()
…
The documentation talks about field_order. The line field_order = ['name', ] in form.py has no effect.
What's wrong?

As documentation states this is ordering of form fields
for example of:
class MyForm(forms.Form):
project = forms.somefield
name = forms.somefield
field_order = ['name', ]
would show name prior to project in form
What you want is change sort order of ModelChoiceField that means you should change your queryset argument
forms.ModelChoiceField(Project.objects.order_by('name'))

You can order them by changing your query to
queryset=Project.objects.order_by("name")
or if you need reverse order ...order_by("-name").

Related

Model Form not displaying

So I created a model form but it's not showing in the page but it's registered on the django admin site.views.py[forms.py
(https://i.stack.imgur.com/Z3qud.png)models.py
the error I keep getting
I tried creating the models using django shell
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from .forms import AttendeeForm
# Create your views here.
def attendees_reg(request):
form = AttendeeForm()
if request.method == 'POST':
form = AttendeeForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Data Has been Saved')
return redirect('/attendees')
return render(request, "templates/attendees_reg.html", {'form':form})
forms.py
from django.forms import ModelForm
from .models import Attendee
class AttendeeForm(ModelForm):
class Meta:
model = Attendee
fields = "all"
template
</h1> <hr>
{% for message in messages %}
<p>{{message}}</p>
{% endfor %}
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
You need to be correct "__all__" instead of "all"
class AttendeeForm(ModelForm):
class Meta:
model = Attendee
fields = "__all__"

Display a form field i.e., a choice field of form in the template django

I've have forms.py file in that i have a choice field which i've to display it in the template.html
forms.py
Choices = [('Yelp',)]
class UtilitiesForm(forms.Form):
api_select = forms.MultipleChoiceField(widget=forms.Select(),
choices=Choices)
text_url = forms.CharField()
template.html
{% block body_content %}
<form action="/utilities/fetch-data/" method="post" id="utitliy__form">
<div class="form-row">
<label>Select an API</label>
{{ form.api_select }}
</div>
</form>
{% endblock body_content %}
i'm getting Value error can you guys help me how to write the choice field in template.html
You need not to do anything with choice field in forms.py you can directly use it in your template.
template
<form action="" method="post">
{% csrf_token %}
<label for="order_no">Order No.:</label>
<input type="text" class='form-control' value="{{Order}}" name="order_no" readonly><br>
<label for="isbn">ISBN No.:</label>
<input type="text" class='form-control' value="{{ISBN}}" name="isbn" readonly><br>
<label for="rate">Rate:</label>{{forms.rate}}(Rate us 10 is the Highest and 1 is the lowest)<br><br>
<label for="comment">Comments</label>{{forms.comment}}<br><br>
<input type="submit" class="btn btn-success">
</form>
Models.py
RATING=( (1,1), (2,2), (3,3), (4,4), (5,5), (6,6), (7,7), (8,8), (9,9), (10,10) )
class returnbook(models.Model):
order_no=models.IntegerField(blank=True,null=True)
isbn=models.CharField(max_length=15)
rate=models.IntegerField(choices=RATING,default='1')
comment=models.TextField(max_length=20000,blank=True)
user=models.CharField(max_length=50)
class Meta:
unique_together = ('order_no', 'isbn')
def __unicode__(self):
return unicode(self.rate)
The choices [Django-doc] should be:
Either an iterable (e.g., a list or tuple) of 2-tuples to use as
choices for this field, or a callable that returns such an iterable.
This argument accepts the same formats as the choices argument to a
model field. See the model field reference documentation on choices
for more details. If the argument is a callable, it is evaluated each
time the field’s form is initialized. Defaults to an empty list.
Here you provide it an iterable of 1-tuples. The tuple specify the value, and the textual representation, for example:
API_SELECT_CHOICES = [('yelp', 'Yelp')]
class UtilitiesForm(forms.Form):
api_select = forms.ChoiceField(
widget=forms.Select,
choices=API_SELECT_CHOICES
)
text_url = forms.CharField()
It is also strange that you used a MultipleChoiceField with a Select widget. Normally a Select widget is used to select exactly one element, whereas a SelectMultiple widget is used to select zero, one, or more elements. So I here changed the field to ChoiceField. A ChoiceField with a Select widget makes sense, and a MultipleChoiceField with a SelectMultiple makes sense, but the other combinations do not make much sense.
Add the choice in form
forms.py
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
status = models.IntegerField(choices=((1, _("Unread")),(2, _("Read"))),default=1)
class Meta:
model = User
fields = ['first_name', 'last_name', 'status']
in views.py
from django.contrib.auth.models import User
from .forms import UserForm # Add form which is written in your forms.py
def index(request):
context = {}
form = UserForm() #Initiate
return render(request, 'index.html', {'form': form})
index.html you will get choice in html
<form action="{% url 'about' %}" method="POST" role="form">
{% csrf_token %}
{{ form }}
</form>
for more details please refer this link

Passing additional form field from HTML to view in Django

I was following the post, when I try to solve my solution but it doesn't work for me.
My problem:
I have Django Model object with 4 attributes.
Let's say I have something like this
class MyModel(models.Model):
user = models.ForeignKey('auth.User', on_delete=models.CASCADE)
first_at = models.IntegerField()
second_at = models.IntegerField()
third = models.TextField()
Then I have some view in which I would like to present the form with this object. But, I would like the user to only insert 2 of them, user and the third parameter need to be filled automatically; user from current user and third from another HTML element (in which row the form was filled).
class HomePage(LoginRequiredMixin, generic.CreateView):
template_name = 'index.html'
model = MyModel
fields = ('first', 'second')
success_url = reverse_lazy('home')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
Then I have in HTML created
<form action="." method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="third" value="{{ item.third }}" />
<input type="submit" value="submit" />
</form>
Does anyone know why this is not working? And or how should I make it work? Is there is a better way?
Marko
You can try this approach
Create a custom form under a forms.py and exclude the fields let's say
class UserForm(forms.ModelForm):
class Meta:
model=Mymodel
exclude = ['user','third']
and in your create view import the form recenlty created and the use it into the CreateView with form_clas
class HomePage(LoginRequiredMixin, generic.CreateView):
form_class = UserForm
template_name = 'index.html'
model = MyModel
fields = ('first', 'second')
success_url = reverse_lazy('home')
I found the solution,
The problem is, that when you use the generic.CreateView and set either fields, or form_class, then this class will only read those fields. Even if you add manually additional input field it will not be passed inside class.
To solve this problem I created form class with hidden field.
class MyForm(forms.ModelForm):
class Meta:
model = models.OrderDetail
fields = ('first', 'second', 'third')
widgets = {
'third' : forms.HiddenInput(),
}
Then I use this form as normal inside view class
class HomePage(LoginRequiredMixin, generic.CreateView):
template_name = 'index.html'
model = MyModel
form_class = forms.MyForm
success_url = reverse_lazy('home')
Then add additional hidden field inside HTML file
<form action="." method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="third" value="someValue" />
<button type="submit" name="_submit" class="btn btn-raised btn-primary">Submit</button>
</form>
This way, you replace your hidden field that come with form.as_p with custom one.
Note: You don't really replace field. If you inspect the code, you will see, that you will have 2 hidden fields, but only one with value. But because both are hidden, no one could add value to another, so the behaviour is the same as the field would be replaced.

Django ModelForm with ManyToManyField wont save to DB

I`m using Django 1.9 with the following:
views.py:
def a_new(request):
# submit button
if request.method == "POST":
form = AForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('ui:config-list')
# first visit
else:
form = AForm()
template = 'api/test_template.html'
context = RequestContext(request, {'form': form})
return render_to_response(template, context)
forms.py:
class AForm(forms.ModelForm):
b= forms.ModelMultipleChoiceField(
queryset=B.objects.all(),
widget=FilteredSelectMultiple("b", is_stacked=False)
)
class Meta:
model = A
fields = ('name', 'b', )
test_template.html
...
<form role="form" class="form-inline" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form.name }}
{{ form.b }}
</div>
<div class="dl-horizontal">
<button type="submit" class="btn btn-success">Save</button>
</div>
</form>
models.py:
class A(models.Model):
name = models.CharField(max_length=100)
b = models.ManyToManyField(B, null=True, blank=True, name='b')
...
The problem is that when I use the Save button - only the name field is created in the item. The b item, that the widget is being used on, is just not being saved to the DB with the new item A created(it does show error if I leave the b field empty so I guess its checking it too).
What can be the problem?
See the documentation about using commit=False when you have a many-to-many field.
Note that there is no reason for you to be using commit=False here though. Remove it, and the second save, and Django will save your values directly.
b is ManyToManyField, it does on saved on the table A. In a different table the relation between A and B is maintained.
If you have an M2M field and do save(commit=False) you need to call this at the end:
form.save_m2m()
See the docs.

CreateView and related model fields with fixed inital values

I'm working with a CreateView where I know what some of the field values will be ahead of time. In the example below, I know that the author field for a new Entry object will be the current user and I use get_initial() to preset this.
Now I would like to omit this field from my template form. I've tried several approaches:
Simply commenting out the author field in the form template leads to an invalid form.
Leaving 'author' out of fields. Nope.
And here's a related problem. The example below involves a relationship to a User object that exists. But what if I need to create an object, say an auth Group for editors? I've tried creating a placeholder group and renaming it ... and, well, that didn't work very well.
#
# model
#
class Author(Model):
name = CharField(max_length = 60)
user = OneToOneField(to = User, related_name = 'author_user', on_delete = CASCADE)
class Entry(Model):
title = CharField(max_length = 60)
author = ForeignKey(to = Author, related_name = 'entry_author')
#
# view
#
class EntryCreateView(CreateView):
model = Entry
fields = ('title', 'author')
def get_initial(self):
initial = super(EntryCreateView, self).get_initial()
initial['author'] = get_object_or_404(Author, user = self.request.user)
return initial
#
# template
#
{% extends "base.html" %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<label for="{{ form.title.id_for_label }}">Title:</label>
{{ form.title }}
<label for="{{ form.author.id_for_label }}">Author:</label>
{{ form.author }}
<p>
<input type="submit" class="btn btn-primary" name="save" value="Save" />
<input type="submit" class="btn btn-primary" name="cancel" value="Cancel" />
</form>
{% endblock %}
You can manually set user in form_valid() method of EntryCreateView class:
class EntryCreateView(CreateView):
model = Entry
fields = ('title',)
def form_valid(self, form):
user = self.request.user
form.instance.user = user
return super(EntryCreateView, self).form_valid(form)
You'll need to create a ModelForm for the customizations you need (https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/).
You can't remove author because it's required on your model currently.
Try something like this:
In forms.py...
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['title', 'author']
def __init__(self, *args, **kwargs):
initial = kwargs.get('initial', {})
self.author = initial.get('author')
super(EntryForm, self).__init__(*args, **kwargs)
You can make modifications to the fields (set to not required, delete a field from the form fields, etc) in __init__ or on the class.
Just import and reference this form in your views to use it.