I have problem with display many to many field in form widget.
Category is not display in template.
Title is ok (is display) but category isn't - category is empty.
What can I do to display many to many fields in my template form with multiplechoice checkboxes?
Why I cant display article categories in widget form?
MODELS.py
article model:
class Article(Created, HitCountMixin):
title = models.CharField(max_length=120)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
category = models.ManyToManyField(ArticleCategory, related_name='articles')
category model:
class ArticleCategory(Created):
category_name = models.CharField(max_length=128)
slug = models.SlugField(null=False, unique=False)
VIEWS:
class UpdateArticleView(LoginRequiredMixin, UpdateView):
template_name = 'news/update_article.html'
form_class = EditArticleForm
model = Article
def get_success_url(self):
pk = self.kwargs["pk"]
slug = self.kwargs['slug']
return reverse_lazy("news:article_detail", kwargs={'pk': pk, 'slug': slug})
FORMS.py
class AddArticleForm(forms.ModelForm):
title = forms.CharField(
label="Tytuł",
max_length=120,
help_text="Tytuł newsa",
widget=forms.TextInput(attrs={"class": "form-control form-control-lg pr-5 shadow p-1 mb-1 bg-white rounded"}),
required=True,
)
category = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple,
)
And in my HTML TEMPLATE:
<form method="post" enctype='multipart/form-data'>
{% csrf_token %}
{{ form.media }}
{# {% crispy form %}#}
{{ form|crispy }}
<button type="submit" class="btn btn-outline-primary">EDYTUJ NEWS</button>
</form>
Your form_class in your view is a EditArticleForm, so you should be careful to use the correct form.
The form field for a ManyToManyField is normally a ModelMultipleChoiceField [Django-doc], but it is not necessary to specify the form field anyway. You can make use of the widgets option:
class EditArticleForm(forms.ModelForm):
title = forms.CharField(
label='Tytuł',
max_length=120,
help_text='Tytuł newsa',
widget=forms.TextInput(
attrs={'class': 'form-control form-control-lg pr-5 shadow p-1 mb-1 bg-white rounded'}
),
required=True,
)
class Meta:
model = Article
widgets = {
'category': forms.CheckboxSelectMultiple
}
you can customize the label with:
class EditArticleForm(forms.ModelForm):
title = forms.CharField(
label='Tytuł',
max_length=120,
help_text='Tytuł newsa',
widget=forms.TextInput(
attrs={'class': 'form-control form-control-lg pr-5 shadow p-1 mb-1 bg-white rounded'}
),
required=True,
)
class Meta:
model = Article
widgets = {
'category': forms.CheckboxSelectMultiple
}
labels = {
'category': 'label of category'
}
Related
I have these two django blog models in models.py
`
class Snippet(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
...
class Post(models.Model):
# id = models.AutoField(primary_key=True) # the same field in comment model for multi-inheritance (post_id)
id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True, primary_key=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True, editable=False) # add unique=True in slug (never repeat)
title = models.CharField(max_length=200, db_index=True, default='')
tag = models.ManyToManyField(Tag, blank=True, help_text="Select a tag for this post", related_name='post_tags')
snippet = models.OneToOneField(Snippet, on_delete=models.CASCADE, related_name='post_snippets')
...
and i have forms to add new post as follows
class PostModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return "Post #%s) %s" % (obj.id, obj.title)
class SnippetForm(forms.ModelForm):
post = PostModelChoiceField(queryset=Post.objects.all())
class Meta:
model = Snippet
fields = '__all__'
class PostForm(forms.ModelForm):
class Meta:
model = Post
#fields = '__all__'
#fields = ['title', 'tag', 'maintainer', 'post_img', 'content', 'snippet', 'genre', 'language', 'video', 'post_type', 'urls', 'views', 'status' ]
labels = {'snippet': _('Add Code'),}
exclude = ('creator', 'slug',)
widgets = {
'snippet': forms.CheckboxInput(attrs={'type': 'checkbox', 'class': 'checkbox', 'id': 'post-snippet'})
}
def clean(self):
snippet = self.cleaned_data.get('snippet')
if snippet:
self.fields_required(snippet.title, snippet.code, snippet.title, snippet.linenos, snippet.language, snippet.style, snippet.highlighted) # ['title', 'code', 'linenos', ....]
else:
self.cleaned_data['snippet'] = False
return self.cleaned_data
def __init__(self, *args, **kwargs):
super(PostForm, self).__init__(*args, **kwargs)
self.queryset = Post.objects.filter(snippet=True)
and views logic to render template
def add_post(request):
if request.method == 'POST':
post_form = PostForm(request.POST, request.FILES, instance=request.user)
snippet = post_form.cleaned_data['snippet']
if snippet:
#snpt = modelformset_factory(Snippet, fields=('title', 'code', 'linenos', 'language', 'style', 'highlighted'))
snpt = Snippet.objects.create(post = request.post, snippet_id = request.post.id)
snippet_form = SnippetForm(request.POST, instance=snpt)
if post_form.is_valid() and snippet_form.is_valid():
post = post_form.save(commit=False)
snpt = snippet_form.save(commit=False)
post.creator = request.user
post.snippet = snpt
post.slug = slugify(post_form.cleaned_data['title'])
post.save() and snpt.save()
obj = post_form.instance
alert = True
return redirect('blog:post_list')
#return render(request, "add_post.html",{'obj':obj, 'alert':alert})
#return HttpResponseRedirect('blog/post_list/success/')
else:
post_form = PostForm()
return render(request, 'blog/add_post.html', {'form': post_form})
`
Now i can’t get the snippet fields in my template when i tick the check box in the template
Here is the form
<form method='POST' class="form" enctype='multipart/form-data'>
{{ form.non_field_errors }} {% csrf_token %} {% for field in form %}
<div class="apply">
{% if field.errors %}
<ol>
{% for error in field.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %} {% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %} {% bootstrap_form form %}
<button class="boxed-btn3 w-100" type="submit">Post</button>
</form>
what’s wrong in this logic why the snippet form doesn’t show up in the template and how to get it live immediately when i check the boolean field add code (snippet) in the page form
please help me
i tried to get all the Snippet model fields into add post model form to show all fields in one form
but can't get the fields while i have all post model fields rendered well but when i checked the
check box field snippet that has been converted into boolean in post form , nothing happens
I am trying to update some information in my Django application but I am getting this error "Cannot assign "9": "Reservation.table" must be a "Tables" instance".
I have tried so manual method also but it still same error.
Error: Cannot assign "9": "Reservation.table" must be a "Tables" instance
views.py
#login_required
def UpdateReservation(request, pk):
table_exists = get_object_or_404(Reservation, id=pk)
form = ReservationForm(instance=table_exists)
if request.method == "POST":
form = ReservationForm(request.POST, instance=table_exists)
if form.is_valid():
form = ReservationForm(request.POST, instance=table_exists)
if form.is_valid():
form.save()
return redirect('view_reservations')
messages.success(request, "successfully updated table")
context = {"form": form}
return render(request, "dashboard/super/landlord/update_reserve.html", context)
models.py
class Reservation(models.Model):
status_choices = (
("pending", "pending"),
("confirmed", "confirmed")
)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.EmailField()
phone = PhoneNumberField(blank=True)
people = models.IntegerField(default=1)
time = models.TimeField()
date_reserved = models.DateField()
date_booked = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=10, choices=status_choices, default="confirmed")
comment = models.TextField(blank=True)
table = models.ForeignKey(Tables, on_delete=models.CASCADE)
def __str__(self):
return self.first_name
forms.py
class ReservationForm(forms.ModelForm):
time = forms.CharField(
widget=forms.TextInput(attrs={'id': 'timepicker',
'class': 'input-group',
'placeholder': '12:00:AM'}))
date_reserved = forms.DateField(widget=forms.TextInput(
attrs={'placeholder': 'yyyy-mm-dd',
'id': 'datepicker'}), required=True,)
comment = forms.CharField(widget=forms.TextInput(
attrs={'placeholder': 'Leave a message'}), required=True,)
first_name = forms.CharField(widget=forms.TextInput(
attrs={'placeholder': 'Leave a message'}), required=False,)
email = forms.CharField(widget=forms.TextInput(
attrs={'placeholder': 'Your Email Address'}), required=True,)
phone = forms.CharField(widget=forms.TextInput(
attrs={'placeholder': 'Your Telephone number'}), required=True,)
table = forms.IntegerField(widget=forms.TextInput(
attrs={'placeholder': 'Table Number'}), required=True,)
class Meta:
model = Reservation
fields = ['first_name', 'email', 'time', 'comment',
'phone', 'date_reserved', 'people', 'table']
template.html
<div class="panel-body">
<form class="form-horizontal" role="form" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label class="col-md-2 control-label">{{ field.label }}</label>
<div class="col-md-10">
{{ field|attr:'class:form-control'}}
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-md-10">
<center><button class="btn btn-primary" type="submit">Update Reservation</button></center>
</div>
</div>
</div>
You can not make use of an IntegerField, since it expects a Table, not an integer for table. You should use a ModelChoiceField and then use a TextInput as widget:
table = forms.ModelChoiceField(
queryset=Table.objects.all()
widget=forms.TextInput(attrs={'placeholder': 'Table Number'}),
required=True
)
In your form remove your table field from the field list above but keep the one in the Meta, its messing with it because the value is in Integer and you have to assign an object.
I have simple django- form:
class ContactUsForm(forms.ModelForm):
class Meta:
model = Contact
fields = ('subject', 'email', 'message')
widgets = {'time': forms.HiddenInput()}
labels = {
'subject': 'my_subject',
'email': 'my_email',
'message': 'my_message',
}
Model:
class Contact(models.Model):
email = models.EmailField(max_length=100)
subject = models.CharField(max_length=100)
message = models.TextField()
time = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.message
And html:
<h2 class="mb-5">Contact</h2>
{% load crispy_forms_filters static %}
<form method="POST" class="post-form">{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-outline-secondary">Send</button>
</form>
How to remove labels above boxes and put it inside? Is it possible to do it with crispy?
Try this !
class ContactUsForm(forms.ModelForm):
subject = forms.CharField(label='Subject', widget=forms.TextInput(attrs={'placeholder': 'Subject'}))
email = forms.EmailField(label='Email', widget=forms.TextInput(attrs={'placeholder': 'Email'}))
message = forms.TextField(label='Message', widget=forms.TextInput(attrs={'placeholder': 'Message'}))
class Meta:
model = Contact
fields = ('subject', 'email', 'message')
This feature is not available in crispy forms. The question below shows a dry way of achieving this using the init method
Use field label as placeholder in django-crispy-forms
Here I am trying to save selected fields in the manytomany field.
When I try to save the selected fields all fields other than selected are also saved. How can i save only the selected fields.
here is my model..
#model
class Products(models.Model):
name = models.CharField(max_length=128)
product_code = models.CharField(max_length=128)
cmp_id = models.ManyToManyField(Components, blank=True)
bay_id = models.ManyToManyField(ScanningBay, blank=True)
def __str__(self):
return self.name
#form
class ProductForm(forms.ModelForm):
name = forms.CharField(max_length=15,widget=forms.TextInput(attrs={'class':'form-control','placeholder': 'Product Name','size': '40'}))
product_code = forms.CharField(max_length=15, widget=forms.TextInput(
attrs={'class': 'form-control', 'placeholder': 'Product Code', 'size': '40'}))
bay = forms.ModelMultipleChoiceField(queryset=ScanningBay.objects.all())
component = forms.ModelMultipleChoiceField(queryset=Components.objects.all())
class Meta:
model = Products
fields = ('name', 'product_code','bay','component')"
#views
def products(request):
if request.method == 'POST':
p_form = ProductForm(request.POST or None)
new = p_form.save(commit=False)
new.save()
z = p_form.save_m2m()
print (z)
return HttpResponse("success")
else:
pdct_form = ProductForm()
return render(request, 'app/products.html', {'pdct':pdct_form})
this is the template rendered
<form id="test" class="impexform" action="{%url 'products'%}" method="POST">
{% csrf_token %}>
{{pdct}}
<button type="submit" class="btn btn-sm btn-danger mt-3"
style="background:#ed2526; border-radius: 30px; width: 8rem;">Add Product</button>
</form>
The fields in your form don't match the fields on your model:
class ProductForm(forms.ModelForm):
...
cmp_id = forms.ModelMultipleChoiceField(queryset=Components.objects.all())
class Meta:
model = Products
fields = ('name', 'product_code','bay','cmp_id')"
I have a model named Customer and modelForm named Customer, but in my form i need more fields than the fields in Model. For example i want a confPass field in my ModelForm.
Code for Model:
class Customer(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField(max_length=100, unique=True)
mobile_no = models.CharField(unique=True, validators=[validate_mobile], max_length=10)
state = models.CharField(choices=STATES, max_length=2)
city = models.CharField(max_length=20)
password = models.CharField(max_length=256)
def __str__(self):
return self.email
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = ['name', 'email', 'mobile_no', 'state', 'city', 'password']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget.attrs.update({'placeholder': 'Enter Name', 'class': 'form-control'})
self.fields['email'].widget.attrs.update({'placeholder': 'Enter Email', 'class': 'form-control'})
self.fields['mobile_no'].widget.attrs.update({'placeholder': 'Enter Mobile Number ', 'class': 'form-control'})
self.fields['state'].widget.attrs.update({'class': 'form-control'})
self.fields['city'].widget.attrs.update({'placeholder': 'Enter City', 'class': 'form-control'})
self.fields['password'].widget.attrs.update({'class': 'form-control'})
Just add the field to your CustomerForm class and include it in fields list:
class CustomerForm(ModelForm):
confPass = forms.CharField()
class Meta:
model = Customer
fields = ['name', 'email', 'mobile_no', 'state', 'city', 'password', 'confPass']
I had to do this for a GenericRelation field, 'task'. I wanted to add a field that was in the model but wouldn't display in the ModelForm. I was able to update the field only using the shell. I added an tag after the form and then processed the response in the def form_valid() function. My problem was that I have a task_app that I use for different models, so I needed a GenericRelation.
views.py
class ProjectModelUpdateView(UpdateView):
model = ProjectModel
# fields = '__all__'
form_class = ProjectModelForm
success_url = '/projects_app/'
def form_valid(self, form):
form.instance.updated_by = self.request.user
project = ProjectModel.objects.get(id=form.instance.id)
project.task.create(created_by=self.request.user, task=self.request.POST['task'])
return super().form_valid(form)
HTML
<form method="post">
{% csrf_token %}
{% for field in form %}
<label class="control-label" for="{{ field.auto_id }}">{{ field.label }}</label>
<div class="col-sm-5 border rounded form-outline">
{{ field }}
</div>
{% endfor %}
<label class="control-label" for="id_task">Task</label>
<div class="col-sm-5 border rounded form-outline">
<input type="text" name="task" maxlength="64" class="form-control" id="id_task">
</div>
<br>
<input type="submit" value="Save">
</form>