Pb initializing ModelForm - python

I am learning Django, and I have a problem with ModelForm. So I have an app which is named mini_url. In this app I have a model :
class MiniURL(models.Model):
url = models.URLField(unique=True)
code = models.CharField(unique=True, max_length=255)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name='Date de création')
pseudo = models.CharField(max_length=30)
nb_acces = models.IntegerField(default=0)
I wanted to create a form based on my model, so I did this in a form.py file :
from django.forms import ModelForm
from mini_url.models import MiniURL
def MiniURLForm(ModelForm):
class Meta:
model = MiniURL
fields = ['url', 'pseudo']
And then in my view I have this :
from django.forms import ModelForm
from mini_url.models import MiniURL
def create_url(request):
if request.method == 'POST':
form = MiniURLForm(request.POST)
if form.is_valid():
new_url = MiniURL()
new_url.url = form.cleaned_data['url']
new_url.pseudo = form.cleaned_data['pseudo']
new_url.code = generer(5)
new_url.save()
else:
form = MiniURLForm()
return render(request, 'mini_url/create_url.html', {'form': form})
Finally my template (mini_url/create_url.html) which shows the form :
<p>
<form action="{% url "mini_url.views.create_url" %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit"/>
</form>
</p>
But when I try to acceed to the template I have this error :
MiniURLForm() missing 1 required positional argument: 'ModelForm'
And it shows me that the error is in my view at the line where there is :
form = MiniURLForm()
So I don't understand why it fails. I did what the doc says I think : https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#topics-forms-modelforms
Anyone can help me ?

You have accidentally defined MiniURLForm as a function instead of a form class.
Change
def MiniURLForm(ModelForm): # wrong
to
class MiniURLForm(ModelForm): # should be a class
When you defined MiniURLForm as a function, Django expected a positional argument as per your definition. Change it to a form class and it should work correctly.
Final Code:
class MiniURLForm(ModelForm):
class Meta:
model = MiniURL
fields = ['url', 'pseudo']

Related

IntegrityError at /collection/order/ FOREIGN KEY constraint failed error while adding a new object

Hi I was just learning django and trying to create a model form with manaytomany relationship between item and order
below is my code snippet.
models.py
class Item(models.Model):
name = models.CharField(max_length=25,default="",primary_key=True)
weight = models.FloatField()
def __str__(self):
return self.name
class Order(models.Model):
customername = models.CharField(max_length=25,default="")
item = models.ManyToManyField(Item,default="")
metal = models.ForeignKey(Material,on_delete=models.CASCADE)
price = models.IntegerField()
place = models.CharField(max_length=25)
orderdate = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.customername
forms.py:
from django import forms
from .models import Order, Material, Item
class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = '__all__'
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = '__all__'
views.py:
def ItemSaveorUpdate(request):
if request.method == 'POST':
form = ItemForm(request.POST)
if form.is_valid():
form.save()
messages.add_message(request,messages.SUCCESS,"Movie rating submitted succesfully")
else:
form = ItemForm()
return render(request,'addItem.html',{"form":form})
def OrderSaveorUpdate(request):
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
form.save()
messages.add_message(request,messages.SUCCESS,"Order added succesfully")
return redirect('material')
elif request.method == 'PUT':
item = Item.objects.get(pk=id)
form = OrderForm(instance=item)
form.save()
else:
#item = Item.objects.get(pk=id)
form = OrderForm()
return render(request,'addOrder.html',{"form":form})
Template additem.html:
<form action="{% url 'item' %}" request="post">
{% csrf_token %}
{{form.as_p }}
<input type="submit" value="add">
</form>
urls.py:
urlpatterns = [
path('item/', views.ItemSaveorUpdate, name="item"),
path('material/', views.MaterialSaveorUpdate, name="material"),
path('order/', views.OrderSaveorUpdate, name="order"),
I am trying to select multiple items while creating an order and after clicking add it is giving the error IntegrityError at /collection/order/
FOREIGN KEY constraint failed. Important to mention that the order is getting added which I can see in admin panel but the items are not getting selected.
Please help to avoid this issue and let me know what I missed here.
Thank you.
The issue solved by removing default for item fields in Order class in models.py
item = models.ManyToManyField(Item,default="")
after removing
item = models.ManyToManyField(Item)
Its is working fine now.
Thank you.

Django image form isn't saving the image

I have a form that involves uploading a profile picture. I have it working so that I can upload images in the /admin/ interface and display them correctly, but I cannot get my Modelform to save the image.
Here is what I have:
models.py
class Candidate(models.Model):
UserID = models.ForeignKey(User, on_delete=models.CASCADE)
ElectionID = models.ForeignKey(Election, on_delete=models.CASCADE)
Bio = models.CharField(max_length=500, blank=True)
ProfilePicture = models.ImageField(upload_to="profilepics/", null=True, blank=True)
forms.py
class AddCandidateForm(forms.ModelForm):
class Meta:
model = Candidate
fields = ['ElectionID', 'Bio', 'ProfilePicture']
cand_reg.html (Template)
{% block content %}
<h1>Register as a candidate</h1>
<form method="POST" class="post-form">
{% csrf_token %}
<h2>Select an election:</h2><br>
{{form.ElectionID}}<br>
<h2>Enter your bio:</h2><br>
{{form.Bio}}<br>
<h2>Upload a profile picture:</h2><br>
{{form.ProfilePicture}}<br>
<button type="submit">Register</button>
</form>
{% endblock %}
When I try the view function like so I get the error:
MultiValueDictKeyError at /register/
"'ProfilePicture'"
views.py
def add_candidate(request):
if request.method == 'POST':
form = AddCandidateForm(request.POST, request.FILES)
if form.is_valid():
candidate = form.save(commit=False)
candidate = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
return redirect('/home/')
else:
form = AddCandidateForm()
return render(request, 'cand_reg.html', {
"form": form
})
views.py
When I remove the offending line, the error goes away.
def add_candidate(request):
if request.method == 'POST':
form = AddCandidateForm(request.POST, request.FILES)
if form.is_valid():
candidate = form.save(commit=False)
# candidate = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
return redirect('/home/')
else:
form = AddCandidateForm()
return render(request, 'cand_reg.html', {
"form": form
})
However, this doesn't actually save the image, so when I try to render it in a separate template, I get an error then.
Can anyone help me understand why the image isn't uploading?
Thanks in advance :)
You must set the ProfilePicture attribute of the model and not the instance itself (candidate = request.FILES['ProfilePicture']).
Change to:
candidate = form.save(commit=False)
candidate.ProfilePicture = request.FILES['ProfilePicture']
candidate.UserID = request.user
candidate.save()
Change your HTML form to accept files as well. Change to: <form method="POST" enctype="multipart/form-data" class="post-form">. When a form includes file inputs (<input type="file" />), then it must be encoded differently than it used when it includes only text. More here. If you right-click and inspect the {{form.ProfilePicture}} you'll see that this is actually a file input.
Extra one:
Please, do not name your class attributes (ProfilePicture, UserID etc) in PascalCase. Use snake_case instead (profile_picture, user_id etc).

Django: UpdateView and ModelForm

I'm having a weird issue when using a ModelForm as a form_class for UpdateView.
First of all: When using the UpdateView without the form_class tag, everything works perfectly. However, when I try to use the ModelForm (because I want to add a MarkdownField) I get <mediwiki.views.MediwikiForm object at 0x7f990dfce080>displayed in my browser window. Just in plain text?
#template/mediwiki/create2.html:
<form action="" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Save" />
</form>
#views.py:
class EntryUpdate(UpdateView):
model = Mediwiki
slug_field = 'non_proprietary_name'
template_name = "mediwiki/create2.html"
form_class = MediwikiForm⋅
#fields = '__all__' #this works...
#forms.py
class MediwikiForm(ModelForm):
# wiki_page_markdown = MarkdownxFormField()
class Meta:
model = Mediwiki⋅
fields = ['non_proprietary_name', 'category', 'wiki_page_markdown']
#models.py
class Mediwiki(models.Model):
non_proprietary_name = models.CharField(max_length = 100, unique = True)
category = models.ManyToManyField(Category)
wiki_page = models.TextField(blank = True)
wiki_page_markdown = models.TextField(blank = True)
def save(self):
import markdown
self.wiki_page = markdown.markdown(self.wiki_page_markdown)
super(Mediwiki, self).save() # Call the "real" save() method.
def get_absolute_url(self): # For redirect after UpdateView
return reverse('entry', kwargs={'slug': self.non_proprietary_name})
def __str__(self):
return self.non_proprietary_name
#urls.py
url(r'^mediwiki/(?P<slug>\D+)/edit$', EntryUpdate.as_view(), name="update"),
Any idea what might cause this error? Any help will be much appreciated...

Django/Python: form data doesn't get stored in database

Django 1.8 / Python 3.4
I wanna add data from an html-form via a Django view named "add" to my database. However, for some reason this just doesn't happen and I can't figure out what's wrong. Presumably the mistake is in the view's code, but what exactly do I need to change?
models.py
from django.db import models
from model_utils import Choices
class Entry(models.Model):
user = models.CharField(max_length=50)
title = models.CharField(max_length=200)
description = models.TextField()
due_date = models.DateField('Date')
due_time = models.TimeField('Time')
STATUS = Choices('Open', 'Done')
status = models.CharField(choices=STATUS, default=STATUS.Open, max_length=4)
def __unicode__(self):
return u"%s %s %s %s %s" % (self.user, self.title, self.description, self.expiry, self.status)
def expiry(self):
return u"%s %s" % (self.due_date, self.due_time)
The interesting part of my add.html
<td><input type="text" name="title"></td>
<td><input type="text" name="description"></td>
<td><input type="text" name="due_date"></td>
<td><input type="text" name="due_time"></td>
<td>
<select name="status" size="1" selected value="Open">
<option>Open</option>
<option>Done</option>
</select>
</td>
forms.py
from django import forms
from django.forms.widgets import TextInput
class EntryForm(forms.Form):
title = forms.CharField(max_length=200)
description = forms.widgets.TextInput()
due_date = forms.DateField()
due_time = forms.TimeField()
status = forms.ChoiceField(choices=[(x, x) for x in range(1, 2)])
And the relevant view in my views.py
from django import forms
from django.shortcuts import render
from django.shortcuts import redirect
from website.list.forms import EntryForm
def add(request):
if request.method == "POST":
form = EntryForm(request.POST)
if form.is_valid():
new_entry = form.save()
new_entry.save()
return redirect('website')
else:
form = EntryForm()
return render(request,'add.html', {'form': form})
Any help is appreciated!
[EDIT]
So, this is what my add.html looks like now:
<form action="." method="post">
{% csrf_token %}
{{ form }}
<br><input type="submit" value="Send"/>
<br><br>Cancel
</form>
And the slightly edited views.py again:
from django import forms
from django.shortcuts import render
from django.shortcuts import redirect
from www.todolist.forms import EntryForm
from django.contrib.auth.models import User
def add(request):
if request.method == "POST":
form = EntryForm(request.POST)
if form.is_valid())
form.save()
return redirect('website')
else:
form = EntryForm()
return render(request,'add.html', {'form': form})
Figured it out ...
This is what forms.py has to look like in order for the save() function to work in the view:
class EntryForm(forms.ModelForm):
CHOICES = (
('1', 'Open'),
('2', 'Done'),
)
title = forms.CharField(max_length=200)
description = forms.CharField(widget=forms.Textarea)
due_date = forms.DateField()
due_time = forms.TimeField()
status = forms.ChoiceField(choices=CHOICES)
class Meta:
model = Entry
fields = '__all__'
The important things to notice are "ModelForm" instead of just "Form" and the class Meta information.
I am guessing you are getting an error here; form = EntryForm(request.POST) but because you are manually writing out the form html instead of using the Django form to do it, you aren't seeing the error.
https://docs.djangoproject.com/en/1.8/topics/forms/#the-template is how you should use Django to render your html for your Django form; and this by default will display any errors the happened when trying to validate your data.

Trouble with Django ModelChoiceField

Hi bit of a beginner question about using django's modelchoicefield in a form I'm building.
I just need get django to display a drop down list of ingredients in a form. I've gotten to the point where the page renders but the form does not, I was getting errors before so I am kind of perplexed at the moment. I was hoping for some guidance.
Using python 2.7.6 and django 1.6.2. If I left anything out let me know.
Thanks!
Code is below:
views:
args = {}
#add csrf sercurity
args.update(csrf(request))
args['form'] = form
return render_to_response('newMeal.html', args)
form:
from django import forms
from models import meals, ingredients, recipe
class mealForm(forms.ModelForm):
breakfast = forms.ModelChoiceField(queryset=recipe.objects.all())
# Lunch = forms.ModelChoiceField(queryset=recipe.objects.all())
# Dinner = forms.ModelChoiceField(queryset=recipe.objects.all())
class Meta:
model = meals
fields = ('Breakfast','Lunch','Dinner','servingDate')
class recipeForm(forms.ModelForm):
class Meta:
model = recipe
fields = ('Name', 'Directions')
template:
{% extends "base.html" %}
{% block content %}
<p>New Meals go here!</p>
<form action="/meals/newmeal/" method="post">{% csrf_token %}
<table class="selection">
{{form.as_table}}
<tr><td colspan="2"><input type="submit" name="submit" value="Add Meal"></td></tr>
</table>
</form>
{% endblock %}
Model;
from django.db import models
import datetime
Create your models here.
class recipe(models.Model):
Name = models.CharField(max_length=200)
Directions = models.TextField()
pub_date = models.DateTimeField(auto_now_add = True)
def __unicode__(self):
return (self.id, self.Name)
class ingredients(models.Model):
Name = models.CharField(max_length=200)
Quantity = models.IntegerField(default=0)
Units = models.CharField(max_length=10)
Recipe = models.ForeignKey(recipe)
def __unicode__(self):
return self.Name
class meals(models.Model):
Breakfast = models.CharField(max_length=200)
Lunch = models.CharField(max_length=200)
Dinner = models.CharField(max_length=200)
servingDate = models.DateTimeField('date published')
did you import the mealForm:
some thing like :from app.forms import mealForm
form is a function. so try:
args['form'] = mealForm()
Note: don't use render_to_response. it is old use render instead(so don't even need csrf)::
from django.shortcuts import render
def...(request):
....
return render(request,'newMeal.html', {'form': mealForm()})

Categories