I want to display just one field from my form that I have created but I am getting 'Could not parse the remainder:' error
Here is my forms.py file
from django import forms
from .models import *
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('prod_name', 'company', 'quantity', 'price', 'units', 'prod_type')
Here is my html file
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form method="POST">
<br>
{% csrf_token %}
{% for field in form %}
{% if field.name=='units' %}
<div class ="form-form row">
<label for="id_{{field.name}}" class="col-2 col-form-label">{{field.label}}</label>
<div class ="col-10">
{{field}}
</div>
</div>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary" name="button">Update Sales</button>
</form>
</div>
{% endblock %}
I just want to display units in my webpage for this module that I am creating
I think you try to solve the problem on the wrong level. You can just construct a form with one field:
from django import forms
from .models import *
class UnitProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('units',)
If you need the other form as well, you can just create an extra one, with a different name, like here UnitProductForm.
Using a form with a subset of fields is not only easier to render. The form will not make modifications to fields of a model object if these are not specified, even if these items are passed in a (forged) POST request. So it makes it more safe to use as well.
If you want to display only prod_name field then you can do it:
{
from django import forms
from .models import *
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('prod_name')
}
Displaying just one field can be controlled from the templates like:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<form method="POST">
{% csrf_token %}
{{ form.units.label_tag }} /*Shows the label for the input field */
{{ form.units }} /*Shows the input field */
<button type="submit" class="btn btn-primary" name="button">Update Sales</button>
</form>
</div>
{% endblock %}
This is from the official documentation, found here.
Note that you will have to handle creation of the object in the backend, if you choose to display only certain fields like this.
Related
I'm new to Django and I have a problem that makes me quite confused. I have a page when users click to change profile, the corresponding page shows up and lets users update their profile. Here is my model:
from django.db import models
import os
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Account(models.Model):
user = models.ForeignKey(User, on_delete="CASCADE")
phone = models.CharField(max_length=18)
room = models.CharField(max_length=8)
dob = models.DateField(default=timezone.datetime.now())
active = models.BooleanField(default=True)
avatar = models.ImageField(upload_to='images/', default=os.path.join(settings.STATIC_ROOT, 'avatar.png'))
def __str__(self):
return self.user.username
Here are my forms:
class UserForm(forms.ModelForm):
first_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
last_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class ProfileForm(forms.ModelForm):
class Meta:
model = Account
fields = ['phone', 'room', 'dob', 'active', 'avatar']
And I have my views.py like this:
def show_form(request):
user_basic_info = UserForm(request.POST)
form = ProfileForm(request.POST)
if form.is_valid() and user_basic_info.is_valid():
form.save() and user_basic_info.save()
messages.sucess(request, _('Your profile has been successfully updated'))
redirect('my_account')
else:
UserForm()
ProfileForm()
context = {
'user_basic_info': user_basic_info,
'form': form,
}
return render(request, 'my_account.html', context)
Here is my_account.html template:
{% extends 'base.html' %}
{% block title %}My account{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item active">Update your information</li>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-6 col-md-8 col-sm-10">
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Save changes</button>
</form>
</div>
</div>
{% endblock %}
And forms.html:
{% load widget_tweaks %}
<table>
<div class="form-group">############
{{ user_basic_info }} ############# This displays first_name, last_name and email. Also the problem's here, I want to make 2 forms in one form with a better style like the form below.
</div>############
</table>
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
<p{% if forloop.last %} class="mb-0"{% endif %}>{{ error }}</p>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %} {% else %} {% render_field field class="form-control is-valid" %} {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text|safe }}
</small> {% endif %}
</div>
{% endfor %}
So when users want to change their profile, those fields first_name, last_name, email, phone, room, dob, active, avatar need to be displayed. But the first 3 fields belong to the User model and the rest fields are defined in my Account model. I want when users submit the form, those fields are linked together, e.g Account is an instance of User and that information is properly saved to the database in Account model (I have watched some tutorials but I still cannot properly do it). And when logging to the page, login authentication using User model, but when updating the profile it's Account model and User model, but there is no relationship between them, how can I fix all of those errors, thanks in advance.
you need to use OneToOne Relationship here since each user has only one and unique profile details. so in your models.py use :-
user = models.OneToOneField(User, on_delete=models.CASCADE)
If you use default user there is 4 way to extends it so here i give a link follow them,
if you use default user you need to use Usercreation form for Register because the user model have password encryption algorithmuse so when you use you user define form it will not store your password
follow instruction for extends user abstract base model
extends user using
registration form using usercreation form
Define view of save data
follow instruction for extends user using one to one
Create new model Profile and give one to one relationship
Create registration form usring model.formplus additional fields you want to take from user define in form class explicity
in view save form and add user reference in Profile model using create method
link:
extend user model
if you use usercreation form
go through i give link if you got error let me know
I want to replace the add object button in the listview of an admin page. The underlying idea is that an administrator can download data on all models in the db, use a tool to edit the data, and then reupload as a CSV file.
In the list view I am struggling to override the form, as setting
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class Meta:
model = MyModel
fields = '__all__'
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
form = SomeModelForm
other stuff
The admin change_list.html is overridden as follows:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools-items %}
<form action="{% url 'admin:custom_submit_row' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>
{{ form.as_p }}
</p>
<p><input type="submit" value="Upload" /><input type="reset" value="Reset"></p>
</form>
{% endblock %}
Previously SomeModel was missing the class Meta, as per sebbs response this is updated. The original error has been resolved but now currently the admin page is displaying the upload and reset buttons but no field for file uploads.
cheers
Edited with sebb's input below. Thanks sebb.
The error fixed was
< class ‘my_model.admin.SomeModelAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'
OP here, solution is as follows:
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
def get_urls(self):
urls = super().get_urls()
my_urls = patterns("",
url(r"^upload_csv/$", self.upload_csv, name='upload_csv')
)
return my_urls + urls
urls = property(get_urls)
def changelist_view(self, *args, **kwargs):
view = super().changelist_view(*args, **kwargs)
view.context_data['submit_csv_form'] = SomeModelForm
return view
def upload_csv(self, request):
if request.method == 'POST':
form = MineDifficultyResourceForm(request.POST, request.FILES)
if form.is_valid():
# process form
with the template overridden as so:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools %}
{% if has_add_permission %}
<div>
<ul class="object-tools">
{% block object-tools-items %}
<form id="upload-csv-form" action="{% url 'admin:upload_csv' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ submit_csv_form.as_p }}</p>
<p>{{ submit_csv_form.csv_file.errors }}</p>
<p><input type="submit" value="Upload" />
<input type="reset" value="Reset"></p>
</form>
{% endblock %}
</ul>
</div>
{% endif %}
{% endblock %}
The form needs some custom validation but otherwise this solves the difficult part of customizing the admin page.
To elaborate what is going on here:
get_urls is overridden so that an additional endpoint can be added to the admin page, this can point to any view, in this case it points upload_csv
changelist_view is overridden to append the form info to the view
the change_list.html template block "object-tools" is overridden with the form fields
Hopefully someone else finds this helpful as well.
to your class SomeModelForm add something like this:
class Meta:
model = YourModel
fields = '__all__'
and change from forms.Form to forms.ModelForm
I am trying to use Update view in django, in the simplest manner, but it is not being updated, rather a new object of the model is being created in the database. I have done the same thing for another model Track, and its working fine. I feel it might be something trivial that might be causing the problem.
I am modifying the PK of the model here. Could this be the reason?
View:
from django.views.generic.edit import UpdateView
from musictracker.models.datamodels.Genre import Genre
class EditGenre(UpdateView):
model = Genre
template_name = "editGenre.html"
fields = ['name']
Template:
{% extends 'base.html' %} {% load addcss %} {% block content %}
<div id="regContainer">
<ul>
<!-- {% if form.errors %} {{form.errors}} {% endif %} -->
</ul>
<div class="form-group">
<form method="post" action="">
{% csrf_token %}
{% for field in form %}
<label class="control-label" for="form-control input-sm">{{field.label_tag }}</label>
<br /> {{field|addcss:"form-control input-sm"}}
<br />
{% endfor %}
<input type="submit" id="register" value="Edit Genre" class="btn btn-default">
</form>
</div>
</div>
{% endblock %}
URLS.py
from django.conf.urls import url
from django.contrib import admin
''' View Imports '''
from views import TrackList
from views import AddTrack
from views import TrackDetail
from views import EditTrack
from views import GenreList
from views import GenreDetail
from views import AddGenre
from views import EditGenre
urlpatterns = [
url(r'^tracks/', TrackList.as_view(),name='all-tracks'),
url(r'^addTrack/', AddTrack.as_view(),name='add-tracks'),
url(r'^editTrack/(?P<pk>[0-9]+)', EditTrack.as_view(),name='edit-track'),
url(r'^track/(?P<pk>[0-9]+)', TrackDetail.as_view(),name='track'),
url(r'^genres/', GenreList.as_view(),name='all-genres'),
url(r'^addGenre/', AddGenre.as_view(),name='add-genre'),
url(r'^editGenre/(?P<pk>[a-zA-Z0-9]+)', EditGenre.as_view(),name='genre'),
url(r'^genre/(?P<pk>[a-zA-Z0-9]+)', GenreDetail.as_view(),name='genre'),
]
Model:
class Genre(models.Model):
'''
This is a model for Genres
'''
name = models.CharField(max_length=20,primary_key=True,editable=True)
songcount = models.IntegerField()
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse('genre', kwargs={'pk': self.pk})
Well, as other folks said in comments, your view creates new object instead of update because you have editable primary key.
You see, undercover UpdateView creates form for your model and calls save on that form.
It's the save method of BaseModelForm which operates self.instance attribute. And if instance isn't being found by pk, new one will be created. So I suggest you to recreate your model with uneditable primary key and leave name as just simple char field.
For future visitors - I experienced the same issue, but did not have an editable primary key. In my case I reused a form for both CreateView and UpdateView and forgot to allow for the difference in form action:
<form role="form" class="form-horizontal" action="{% url createobject' %}" method="post" multipart/form-data">
But it should have been
{% if not object %}
<form role="form" class="form-horizontal" action="{% url 'object:createobject' %}" method="post" multipart/form-data">
{% else %}
<form role="form" class="form-horizontal" action="{% url 'object:updateobject' object.pk %}" method="post" enctype="multipart/form-data">
{% endif %}
So, whenever I submitted the form, the action called my Createview instead of my UpdateView.
Hi i used formsets in generic FormView like this:
class RequestRecommendationView(FormView):
template_name = "account/stepfour.html"
form_class = formset_factory(StepFourForm)
def form_valid(self,form):
print form.is_valid()
cleaned_data = form.cleaned_data
# return redirect(reverse("some_url_name"))
form for formset_factory is like this:
class StepFourForm(forms.Form):
contact_person = forms.CharField(required=True)
email = forms.EmailField(required=True)
company = forms.CharField(required=True)
request_message = forms.CharField(required=True)
my html structure is like this:
<div style="padding-top:100px;padding-left:10px;">
<h4> Request a Recommendation </h4>
<form method="post" action="">
{% csrf_token %}
<table id="myForm">
<tbody>
{% for f in form %}
{% for field in f %}
<tr>
<td>{{field.label_tag}}</td>
<td>{{field}}</td>
{% for error in field.errors %}
<td><span>{{ error }}</span></td>
{% endfor %}
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
<button class="btn btn-primary btn-xlarge" type="submit" name="submit">Request Now</button>
{{ form.management_form }}
</form>
</div>
Then i used django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/)
to add/remove extra forms through these:
<script type="text/javascript">
$(function() {
$('#myForm tbody').formset();
})
</script>
the problem is:
if i leave the form empty,(every field is required), it manages to get to form_valid() of my class-view (though it should not), if i fill one of the fields (leaving others unfilled), it displays the errors associated message successfully. why is this happening ? what should i do to fix it ? is providing form_class a formset is behind all of this ?
This question has been asked 6 years ago, I found it because i faced the same issue, since it is unanswered, I'll provide the solution i found.
according to the documentation to validate a minimum of forms, you have to provide a min_num and set validate_min=True in the formset_factory:
formset = formset_factory(your_form, min_num=2, validate_min=True, extra=2)
I have a model:
class Setting(models.Model):
class Meta:
abstract = True
name = models.CharField(max_length=120, primary_key=True)
description = models.CharField(max_length=300, blank=True)
class IntegerSetting(Setting):
value = models.IntegerField()
I would like to create a form that looks something like:
<form method="POST" action="">
{% for model in models %}
<label>{{model.name}}</label> <input value='{{model.value}}' />
<p>{{model.description}}</p>
{% endfor %}
</form>
I'm not quite sure how to go about doing this. Perhaps I need to use a formset?
from django.forms.models import modelformset_factory
from apps.about.models import Setting, IntegerSetting
def site_settings(request):
formset = modelformset_factory(IntegerSetting)()
return render_to_response("about/admin/site-settings.html", {'formset': formset}, RequestContext(request, {}))
Then in the template, I'd want to render the form differently than default. I'm not quite sure how to go about accessing the model properties, however. Is this the right approach, or is there another way I should be going about doing this?
Update: This is what I'm currently doing. It renders exactly as I'd like it to, aside from the styling. However, I feel that it's deeply hacky:
class SettingsForm(ModelForm):
class Meta:
model = IntegerSetting
def as_table(self):
bound_field = BoundField(self, self.fields['value'], 'value')
return mark_safe("<tr><td><label>%s</label></td><td>%s\n<p class='help'>%s</p></td></tr>" % (self.instance.name,
self.instance.description,
bound_field.__unicode__()))
def edit_settings(request):
forms = [SettingsForm(instance=intSetting) for intSetting in IntegerSetting.objects.all()]
return render_to_response("admin/edit-settings.html", {'forms': forms}, RequestContext(request, {}))
edit-settings.html:
{% extends "admin/base_site.html" %}
{% block title %}System Settings{% endblock %}
{% block content %}
<form method="post" action="">
<table>
{% for form in forms %}
{{form}}
{% endfor %}
</table>
</form>
{% endblock %}
Is there a better approach to this?
Also, I'm not sure if I'll encounter problems when the form is submitted or not.
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
You can find the complete documentation here:
http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template
I don't think you need a formset here. Take a look here if you want a custom template for one view. If you want to create your own {{ form.as_foobar }}, just subclass forms.Form, something like this:
class MyForm(forms.Form):
def as_foobar(self):
return self._html_output(
normal_row = u'%(label)s %(field)s%(help_text)s',
error_row = u'%s',
row_ender = '',
help_text_html = u' %s',
errors_on_separate_row = False)
and just use it in your forms.py:
class ContactForm(MyForm):
# ..
For whoever needs the <table> version of jbcurtin's answer:
<form method="post">{% csrf_token %}
<table>
{% for field in form %}
<tr>
<th>{{field.label_tag}}</th>
<td>
{{ field.errors }}
{{ field }}
</td>
</tr>
{% endfor %}
</table>
<hr/>
<input type="submit" value="Conferma" />
</form>
Looks like you might be interested in django-floppyforms (docs), which gives you much more control over field rendering.