I am trying to make a Django ModelForm that retrieves data from my database using the GET method. When I click the submit button nothing happens. What am I doing wrong?
HTML doc
<form role="form" action="" method="GET" id="form-map" class="form-map form-search">
<h2>Search Properties</h2>
{% csrf_token %}
{{ form.as_p }}
<input type="submit" action= "" class="btn btn-default" value="Submit">
<input type="reset" class="btn btn-default" value="Reset">
</form><!-- /#form-map -->
forms.py
from django import forms
from .models import StLouisCitySale208
from django.forms import ModelForm, ModelMultipleChoiceField
class StLouisCitySale208Form(ModelForm):
required_css_class = 'form-group'
landuse = forms.ModelMultipleChoiceField(label='Land use', widget=forms.SelectMultiple, queryset=StLouisCitySale208.objects.values_list('landuse', flat=True).distinct())
neighborho =forms.ModelMultipleChoiceField(label='Neighborhood',widget=forms.SelectMultiple, queryset=StLouisCitySale208.objects.values_list('neighborho', flat=True).distinct())
policedist = forms.ModelMultipleChoiceField(label='Police district',widget=forms.SelectMultiple,queryset=StLouisCitySale208.objects.values_list('policedist', flat=True).distinct())
class Meta:
model = StLouisCitySale208
fields = ['landuse', 'neighborho', 'policedist', 'precinct20','vacantland', 'ward20', 'zip', 'zoning','asmtimprov', 'asmtland', 'asmttotal', 'frontage', 'landarea','numbldgs', 'numunits']
views.py
from django.views.generic import FormView, TemplateView
from .forms import StLouisCitySale208Form
class StLouisCitySale208View(FormView):
form_class = StLouisCitySale208Form
template_name = 'maps/StlouiscitySale208.html'
maps/urls.py
from django.urls import path
from .views import StLouisCitySale208View, ComingSoonView
app_name = 'maps'
urlpatterns = [
path("maps/stlouiscitysale208",StLouisCitySale208View.as_view(),name="stlouiscitysale208"),
path('maps/coming_soon', ComingSoonView.as_view(), name="coming_soon")
]
You need a get method in your class to tell the button what to do.
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')
https://docs.djangoproject.com/en/4.0/topics/class-based-views/intro/
Your form currently has method="GET" which is something you'd use for search, or some other operation which doesn't change the state of the application.
If that's what you want to do, and you're using existing data, through a form, to allow users to query the database, then you'll need to implement a get method on the view in order to implement the logic for this. The following should help with the get() method for FormView;
http://ccbv.co.uk/projects/Django/4.0/django.views.generic.edit/FormView/#get
It sounds like you're hoping to create objects using your model form, so change that to method="POST" and you'll at least allow the application to create your object. There may be more to debug at that point, but you need to start by sending data to the server.
Related
I am creating an app where user can search for recipes by ingredients. I want that logged in user can add recipe by himself. I have created form where i am using ModelForm. Now i want to do that after user push submit recipe will be added/saved to recipes which i can see in admin panel and also it will be possible to search for it, but now it looks like it is impossible to save the new recipe...
My code in view:
def add_recipe(request):
if not request.user.is_authenticated:
return redirect('login_required')
add_recipe = RecipeForm(request.POST or None)
if add_recipe.is_valid():
print("your recipe has been added!")
add_recipe.save()
template = "drinks/add_recipe.html"
return render(request, template, {'RecipeForm': add_recipe})
My form:
from django.forms import ModelForm
from drinks.models import Recipe
class RecipeForm(ModelForm):
class Meta:
model = Recipe
fields = ['recipe_name', 'preparation', 'ingredients']
My templates add_recipe:
<form method="post" action="">
{% csrf_token %}
<table>
{{RecipeForm}}
</table>
<input type="submit" value="Add recipe"/>
</form>
my urls:
urlpatterns = [
path('', views.drink_list, name='drink_list'),
path('search/', views.search_results, name='search_results'),
path('no_name/', views.drink_list, name='drink_list'),
path('signup/', views.signup, name='signup'),
path('add_recipe/', views.add_recipe, name='add_recipe'),
path('login_required/', views.login_required, name='login_required'),
]
I am not sure what you are trying to do with your views (their names are not very explicit), but have you registered the view through your urls.py file?
Also, action="" in your template won't do anything. You need to specify the url to send your post request! action should not be equaled to "", but to the url you want to submit your form. In your case, you should have action="{% url 'add_recipe' %}"
I am trying to create a Django web app that accepts text in a form/textbox, processes it and redirects to a webpage showing the processed text . I have written a half-functioning app and find de-bugging quite challenging because I don't understand most of what I've done. I'm hoping you will help me understand a few concepts, Linking to resources, also appreciated.
Consider this simple model:
class ThanksModel(models.Model):
thanks_text = models.CharField(max_length=200)
Is the only way to set the text of thanks_text through the manage.py shell? This feels like a pain if I just have one piece of text that I want to display. If I want to display a webpage that just says 'hi', do I still need to create a model?
Consider the view and template below:
views.py
class TestView(generic.FormView):
template_name = 'vader/test.html'
form_class = TestForm
success_url = '/thanks/'
test.html
<form action = "{% url 'vader:thanks'%}" method="post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit">
</form>
I need to create another model, view and html template and update urls.py for '/thanks/' in order for the success_url to redirect correctly? (That's what I've done.) Do I need to use reverse() or reverse_lazy() the success_url in this situation?
Models are used when you are dealing with Objects and Data and DataBases that can contain a lot of information.
For Example A Person would be a model. their attributes would be age, name, nationality etc.
models.py
class Person(models.Model):
Name = models.CharField(max_length=50)
age = models.IntegerField()
nationality = models.CharField(max_length=50)
Thi deals with multiple bits of information for one object. (the object being the person)
A Thank you message would not need this? so scrap the model for the thank you message. just have views where you create the view using a templates and setting the view to a url.
views.py
class TestView(generic.FormView):
template_name = 'vader/test.html' # self explantory
form_class = TestForm # grabs the test form object
success_url = reverse_lazy('vader:thanks') # this makes sure you can use the name of the url instead of the path
def ThanksView(request): # its simple so you don't even need a class base view. a function view will do just fine.
return render(request,"thanks.html")
test.html
<form action = "{% url 'vader:thanks'%}" method="post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit">
</form>
thanks.html
<h1>Thank you for Submitting</h1>
<h2> Come Again </h2>
url.py
from django.urls import path
from djangoapp5 import views
urlpatterns = [
path('', TestView.as_view(), name='test_form'),
path('thanks/', views.ThanksView, name='vader:thanks'),
]
I haven't tested this but hopefully it helps and guide you in the right direction
I have problem when I want to use simple CreateView for creating new user. Everything is ok, I can create user, but when I want logging with new created user, I cant do it.
I got this type of my password in admin:
Invalid password format or unknown hashing algorithm.
Raw passwords are not stored, so there is no way to see this user's password, but you can change the password using this form.
This is my code:
model.py
from django.db import models
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import AbstractUser, UserManager
class CustomUser(AbstractUser):
"""app setting of user"""
url = models.URLField(u'Site URL', max_length=100, null=True, unique=True)
admin.site.register(CustomUser, UserAdmin)
urls.py
from django.conf.urls.defaults import *
from models import CustomUser
from django.views.generic import CreateView
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
urlpatterns = patterns('',
url(r'^create_user/$',(CreateView.as_view(model=CustomUser, get_success_url =lambda: reverse('create_user'),
template_name="create_user.html")), name='create_user'),
)
create_user.html
<div title="Create Form " id="/create_user">
<p> <b>Create account:</b> </p>
{{ form.errors }}
<form action="" method="post" id="id_create_user" >
{% csrf_token %}
{{ form.as_p }}
<div>
<input type="submit" value="Create account" style="">
</div>
</form>
</div>
And after creating user, I have to log in as admin and change this password, and after that everything will be ok.
What should I do to solve the problem?
Thank you!
The problem is that CreateView is generating a form automatically based on the model, which means it's writing directly to the password field rather than using the correct API for creating a user.
Try this form instead, it'll handle it for you:
from django.contrib.auth.forms import UserCreationForm
urlpatterns = patterns('',
url(r'^create_user/$',(CreateView.as_view(model=CustomUser, get_success_url =lambda: reverse('create_user'), form_class=UserCreationForm, template_name="create_user.html")), name='create_user'),
)
These forms essentially give you the same as what you see in the admin, which is a good starting point, if you're using a custom user model you might want to do some additional work to get your customisations in.
Here's the source code for the supplied UserCreationForm: https://github.com/django/django/blob/stable/1.5.x/django/contrib/auth/forms.py#L61-L110
You can re-implement it yourself as a normal ModelForm, the key thing you must include is the save method where user.set_password is called.
I'm new at django and I'm having problems with a simple form POST.I have a ModelForm in forms.py and when user enters information in html, views.py taks it and saves it. However, I keep getting an error saying it can't find the view doesn't exist in view.py. Please help me find the error. Thank you!
urls.py
urlpatterns = patterns('',
(r'^mypage/(?P<username>\w+)/$', 'recipeapp.views.my_view'),
forms.py
class NewRecipeForm(forms.ModelForm):
user_info = forms.ForeignKey(User)
title = forms.CharField(min_length=2,max_length=50,required=True,)
post_date = forms.DateField(auto_now=True)
ingredients = forms.TextField(widget=forms.Textarea(),)
picture = forms.ImageField(upload_to='photos/%Y/%m/%d',)
content = forms.TextField(widget=forms.Textarea(),)
views.py
#csrf_protect
from recipeapp.forms import NewRecipeForm
def my_view(request,username):
if request.method == 'POST':
form = NewRecipeForm(request.POST)
if form.is_valid():
form.save()
else:
form = NewRecipeForm()
return render_to_response('postlogin.html',{'username':username},{'form': form}, RequestContext(request))
postlogin.html
<form action="" method="post" id="form">
{% csrf_token %}
<div id="dish-name">
<label><p>Dish name</p></label>
{{form.title}}
</div>
<div id="ingredients">
<label><p>Ingredients</p></label>
{{form.ingredients}}
</div>
<div id="content">
<label><p>Content</p></label>
{{form.content}}
</div>
{{form.picture}}
</form>
Is that really your whole views.py? You have at least three issues:
Firstly, you haven't imported csrf_protect - like any name, a decorator needs to be defined before you can use it.
Secondly, you have to decorate an actual function, not a file. The decorator should go just before the function definition for my_view.
Thirdly, your indentation is broken - the def should not be indented at all.
Given all those, I expect that Python is failing to import your views because of syntax errors.
Also note that you shouldn't really use csrf_protect - you should enable CSRF protection in your middleware (it's on by default) and only use the csrf_exempt decorator, and then only on very very rare occasions.
It seems simple to me. If a user is authenticated, auto populate the relavent form fields and don't show them. If a user isn't authenticated, show the form fields. I've been looking everywhere and I can't seem to find the answer. Does anyone know of some way to address this?
in your template you could do something like this:
{% if user.is_authenticated %}
<form>
<input type="hidden" name="username" value="{{ user.username }}" />
</form>
{% else %}
<!-- use your "regular" form here -->
Hope this helps...
This example come from real system, I've worked on. Hope that helps you out.
import datetime
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import force_unicode
import django.contrib.comments.forms
from current_user.middleware import get_current_user
class AuthCommentForm(django.contrib.comments.forms.CommentForm):
def get_comment_create_data(self):
"""
Returns the dict of data to be used to create a comment. Subclasses in
custom comment apps that override get_comment_model can override this
method to add extra fields onto a custom comment model.
"""
return dict(
content_type=ContentType.objects.get_for_model(self.target_object),
object_pk=force_unicode(self.target_object._get_pk_val()),
user_name=get_current_user().username,
user_email=get_current_user().email,
user_url='',
comment=self.cleaned_data["comment"],
submit_date=datetime.datetime.now(),
site_id=settings.SITE_ID,
is_public=True,
is_removed=False,
)
AuthCommentForm.base_fields.pop('url')
AuthCommentForm.base_fields.pop('name')
AuthCommentForm.base_fields.pop('email')
AuthCommentForm.base_fields.pop('honeypot')
AuthCommentForm.base_fields['comment'].label = False