I am trying to create "Edit" for my form.
urls.py
url(r'^app_1/(?P<id>[-\w]+)/edit/$',views.edit, name = 'edit'),
forms.py
class ClanakForma(forms.ModelForm):
class Meta:
model = Clanak
fields = '__all__'
models.py
class Clanak(models.Model):
naslov = models.CharField(null=False, blank=True, max_length=120)
datumObjave = models.DateField(null=False, blank=False)
autor = models.CharField(null=False, blank=True, max_length=50)
email = models.EmailField(max_length=75, null=True, blank=True)
def __str__(self):
return str(self.naslov) + ', ' + str(self.datumObjave) + ', ' + str(self.autor)
views.py
def edit(request, id):
data = get_object_or_404(Clanak, id = id)
if request.method == "POST":
form = ClanakForma(request.Clanak, instance=data)
if form.is_vaild():
data = form.save(commit=False)
data.naslov = request.user
data.datumObjave = request.user
data.autor = request.user
data.email = request.user
return redirect('readAllNew')
else:
form = ClanakForma(instance=data)
template = 'readAllNew.html'
context = {'form': form}
return render(request, template, context)
readAllNew.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<table border="1">
<tr>
<th>Naslov</th>
<th>Datum</th>
<th>Autor</th>
<th>Mail</th>
</tr>
{% for x in data %}
<tr>
<td>{{x.naslov}}</td>
<td>{{x.datumObjave}}</td>
<td>{{x.autor}}</td>
<td>{{x.email}}</td>
<td>delete</td>
<td>edit</td>
</tr>
{% endfor %}
</table>
</body>
</html>
So when I hit edit link at my "readAllNew.html" I get error:
TypeError at /app_1/5/edit/
init() got an unexpected keyword argument 'instance'
I think something is wrong with my view but I am not sure what.
-------------------------------UPDATE--------------------------------
As suggested I edited "forms.py" but now I am not seeing any form field so I can't edit nothing:
See screenshot
---------------- UPDATE 2 -------------------------
I created new html file as "edit.html"
I edited "views.py":
def edit(request, id):
data = get_object_or_404(Clanak, id = id)
if request.method == "POST":
form = ClanakForma(instance=data)
if form.is_vaild():
data = form.save(commit=False)
data.naslov = request.user
data.datumObjave = request.user
data.autor = request.user
data.email = request.user
return redirect('readAllNew.html')
else:
form = ClanakForma(instance=data)
template = 'edit.html'
context = {'form': form}
return render(request, template, context)
Now I see fields and informations in it properly, but when I change something and click on "SUBMIT" I get error:
AttributeError at /app_1/6/edit/
'ClanakForma' object has no attribute 'is_vaild'
Use forms.ModelForm instead of forms.Form
class Forma(forms.ModelForm):
naslov = forms.CharField(label='naslov')
datumObjave = forms.DateField(label='datumObjave')
autor = forms.CharField(label='autor')
email = forms.EmailField(label='email')
class Meta:
model = Clanak
fields = ('naslov', 'datumObjave', 'autor', 'email')
If you want to use all the fields of Model class in your form, you could specify the fields attribute of Meta class as fields = '__all__'
#example
class Forma(forms.ModelForm):
class Meta:
model = Clanak
fields = '__all__'
If you are using forms.ModelForm, you could avoid most of the implementation which makes things easier :)
Update
You need to render the form in your template.So, change your template as
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
You can't pass instance to simple form - it has to be ModelForm. Use this:
class Forma(forms.ModelForm):
class Meta:
model = Clanak
fields = ['naslov', 'datumObjave', 'autor', 'email']
labels = {
'naslov': 'naslov',
'datumObjave': 'datumObjave',
'autor': 'autor',
'email': 'email'
}
Related
Currently, the template is only generating the Submit button without any input fields.
Also, if I change fields = "all" to fields= ["email","name"] it tells me that these fields do not exist.
Model:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True, label='Email')
name = CharField(required=True, label='Name')
Serializer:
class SubscribeForm(forms.ModelForm):
class Meta:
model = NewsletterSubscriber
fields = "__all__"
View:
def subscribe(request):
form = SubscribeForm()
if request.method == 'POST':
form = SubscribeForm(request.POST)
if form.is_valid():
form.save()
# redirect to a success page
return render(request, 'subscribe.html', {'subscribeForm': form})
Template:
<form action="{% url 'subscribe' %}" method="post">
{% csrf_token %}
{{ subscribeForm.as_p }}
<input type="submit" value="Subscribe">
</form>
Give this a try:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True)
name = CharField(required=True)
class SubscribeForm(forms.ModelForm):
class Meta:
model = NewsletterSubscriber
fields = ['email', 'name']
labels = {'email': 'Email', 'name': 'Name'}
Instead of fields you could instead also go for exclude which would then obviously list the fields that you do not want to show up.
All these attributes you can put in the Meta class: Modelformfactory
Solved.
Wrong:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True, label='Email')
name = CharField(required=True, label='Name')
Correct:
class NewsletterSubscriber(models.Model):
email = models.EmailField(required=True, label='Email')
name = models.CharField(required=True, label='Name')
Problem description: UserProfile form doesn't save any data.
I am creating a new User and automatically create a UserProfile object for him (so I'm extending UserProfile), so I can go to admin page and fill all the fields . But when I'm trying to do it from client side, my form just doesn't catch the data.
Also the strangest moment is that I can change username and email using UserChangeForm, so I'm trying to do the same for UserProfileObject.
models.py:
class UserProfile(models.Model):
user = models.OneToOneField(User)
image = models.ImageField(upload_to='profile_image', blank=True)
title = models.CharField(max_length=100, default = '')
first_name = models.CharField(max_length=200, default = '')
last_name = models.CharField(max_length=200, default = '')
subject = models.ManyToManyField('Subject', related_name='tutor_type', default = '', help_text="Select a subject")
AREA_STATUS = (
('Jerusalem', 'Jerusalem'),
('Tel Aviv', 'Tel Aviv'),
('Haifa', 'Haifa'),
('Eilat', 'Eilat')
)
area = models.CharField(max_length=200, choices=AREA_STATUS, blank=True, default='', help_text='Tutor area')
# Foreign Key used because tutor can only have one area, but area can have multiple tutors
# Author as a string rather than object because it hasn't been declared yet in file.
description = models.TextField(max_length=4000, help_text="Enter a brief description about yourself")
charge = models.IntegerField(default = '0')
# ManyToManyField used because Subject can contain many tutors. Tutors can cover many subjects.
# Subject declared as an object because it has already been defined.
LANGUAGE_CHOICES = (
('English','English'),
('Hebrew','Hebrew'),
('Russian','Russian'),
('French','French'),
('Arabic','Arabic'),
)
language = models.CharField('Language', choices = LANGUAGE_CHOICES, max_length=50, null=True)
def __str__(self):
return self.user.username
def display_subject(self):
"""
Creates a string for the subject. This is required to display subject in Admin.
"""
return ', '.join([ subject.name for subject in self.subject.all()[:3] ])
display_subject.short_description = 'Subject'
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender = User)
forms.py::
class EditProfileForm(UserChangeForm):
class Meta:
model = User
fields = (
'username',
'email',
'password'
)
class EditExtendedProfileForm(UserChangeForm):
class Meta:
model = UserProfile
fields = '__all__'
exclude = ('user',)
views.py:
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('accounts:view_profile'))
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/edit_profile.html', args)
def edit_extended_profile(request):
if request.method == "POST":
form = EditExtendedProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect(reverse('accounts:view_profile'))
else:
return redirect(reverse('accounts:edit_extended_profile'))
else:
form = EditExtendedProfileForm(instance = request.user)
args = {'form':form}
return render(request, 'accounts/edit_extended_profile.html', args)
edit_extended_profile.html:
{% extends "base.html" %}
{% block head %}
<title>Profile</title>
{% endblock %}
{% block body %}
<div class = "container">
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<button type = "submit" class = "btn btn-success">Submit</button>
</form>
</div>
{% endblock %}
and it is the same template as for edit_profile view.
No traceback, no errors. Any help will be appreciated. Thanks in advance.
I am probably missing something very simple, because my model form is not shown at the template. The code is very simple:
models.py:
class Story(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200)
content = models.TextField()
picture = models.ImageField(upload_to = 'images/post_images')
date = models.DateTimeField(auto_now_add=True)
forms.py:
class StoryForm(forms.ModelForm):
class Meta:
model = Story
views.py:
from sfv.forms import StoryForm
#login_required(redirect_field_name=None)
def restricted(request):
user = request.user
form = StoryForm()
#graph = get_persistent_graph(request)
return render(request, "restricted.html", {user : 'user', form : 'form',})
template:
<form method = 'POST' action = ''>
<table>
{{ form }}
<table>
</form>
I have also tried form.as_p, that didnt help.
Change your render method from
return render(request, "restricted.html", {user : 'user', form : 'form',})
to
return render(request, "restricted.html", { 'user' : user, 'form' : form})
The key and value in the context dictionary were interchanged. Hence the issue.
I have different models:
Cars
Pictures (models.ForeignKey(Cars))
CarsOptions(models.OneToOneField(Cars))
Then I want, that user can add new cars. Forms.py:
class NewCarsForm(ModelForm):
class Meta:
model = Cars
exclude = ('checked','user')
In views.py:
#login_required
def add_car(request):
form = NewCarsForm(request.POST or None)
if form.is_valid():
cmodel = form.save()
cmodel.save()
return redirect(profile)
return render(request, 'add_car.html', { 'form': form,})
I have a few questions (yes, I read this).
As you can see, user can add only "car", not pictures and options. How to do this on one page in one form?
exclude = ('checked','user'), it means, that I want to make all new positions with checked=0, so I can filter them. And the user-field - users cant choose user in a list. How to take user id (who adds car) in form.save()?
Thanks.
Update:
class Pictures(models.Model):
cars = models.ForeignKey(Cars, related_name='pictures')
width = models.PositiveIntegerField(editable=False, default=640)
height = models.PositiveIntegerField(editable=False, default=480)
image = models.ImageField(upload_to=lambda inst, fname: 'users_img/' + 'cars' + fname, height_field='height', width_field='width', max_length=100)
def __unicode__(self):
return str(self.id)
forms.py
class NewCarsForm(ModelForm):
class Meta:
model = Cars
exclude = ('checked','user')
PicturesFormset = inlineformset_factory(Cars, Pictures,
fields=('field_name', 'field_name'), can_delete=True)
CarsOptionsFormset = inlineformset_factory(Cars, CarsOptions,
fields=('field_name', 'field_name'), can_delete=True)
views.py
#login_required
def add_car(request):
cars = Cars(user=request.user)
if request.method == 'POST':
form = NewCarsForm(request.POST, instance=cars)
if form.is_valid():
cmodel = form.save()
picture_formset = PicturesFormset(request.POST, request.FILES,
instance=cmodel)
if picture_formset.is_valid():
picture_formset.save()
option_formset = CarsOptionsFormset(request.POST, instance=cmodel)
if option_formset.is_valid():
option_formset.save()
return redirect(profile)
form = NewCarsForm()
picture_formset = PicturesFormset(instance=Cars())
option_formset = CarsOptionsFormset(instance=Cars())
return render(request, 'add_car.html', {
'form': form,
'picture_formset': picture_formset,
'option_formset': option_formset,
})
template
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<h4>Car:</h4>
{{ form.as_p }}
<h4>Picture:</h4>
{{ picture_formset.as_p }}
<h4>Options:</h4>
{{ option_formset.as_p }}
<input type="submit" value="Submit">
</form>
I can't figure out how to store a simple form in the database. I think I'm quite close but there is probably something wrong in my views.py. Here is my code, any ideas what I'm doing wrong? (also on dpaste)
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(forms.Form):
name = forms.CharField(max_length=30)
# views.py
#login_required
def newCategory(request):
if request.method == 'POST':
username = request.user.username
cform = CategoryForm(request.POST)
if cform.is_valid():
formInstance = cform.save(commit = False)
formInstance.user = username
formInstance.name = cform.cleaned_data['name']
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
formInstance.save()
# return HttpResponseRedirect('new-category/')
else:
form = CategoryForm()
context = {'form': form}
return render_to_response('new-category.html', context, context_instance=RequestContext(request))
# new-category.html
<h3>Insert New Category</h3>
<form action="/" method="post" id="food-form">{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="foodForm" value="Save" />
</form>
The line below is not useful at it current position. That command will perform a database query and assign the result as a queryset, before you have saved the form data.
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
This should work:
With cform as a normal Form:
if cform.is_valid():
formInstance = IngredienceCategory(user=request.user, cform.cleaned_data['name'])
formInstance.save()
If cform had been a ModelForm you could do:
if cform.is_valid():
formInstance = cform.save(commit=False)
formInstance.user = request.user
formInstance.save()
I do recommend you to check out ModelForms since it will build the cleaning functionality based on your model.
You should inherit from ModelForm
from django.forms import ModelForm
class CategoryForm(ModelForm):
class Meta:
model = IngredienceCategory
Refer to https://docs.djangoproject.com/en/dev/topics/forms/modelforms/ for how to render form and save it to database.