I can't post in Django, because when I import an image it doesn't work for me. it tells me that there's no file selected but I selected one.
This is the post model that I created, models.py file:
class Post(models.Model):
publisher = models.ForeignKey(User,on_delete=models.CASCADE)
caption = models.CharField(max_length=100)
date_created = models.DateTimeField(default=timezone.now())
image = models.ImageField(upload_to="post_images")
def __str__(self):
return self.caption
here's the forms.py file for the Post model:
from django import forms
from .models import Post
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['caption','image']
here's the Publish function in views.py file which implements the logic for my publish feature:
#login_required
def Publish(request):
if request.method == "POST":
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.publisher = request.user
form.save()
return redirect("home")
else:
form = CreatePostForm()
return render(request,"posts/publish.html",{
"form":form,
})
int the urls.py file:
from django.urls import path
from . import views
urlpatterns = [
path('publish/',views.Publish,name="publish"),
path('',views.home,name="home"),
]
and here's in html template:
{% extends "users/base.html" %}
{% load crispy_forms_tags %}
{% block title %}create{% endblock title%}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-6 col-md-5 authentification">
<div class="form-header">
<h1>
publish
</h1>
</div>
<div class="form-body">
<form method="POST">
<fieldset class="form-group" enctype="multipart/form-data">
{% csrf_token %}
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary form-control">publish</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
the Django version used is 2.2 and the Python 3.8. and Windows 10 Pro
You should alter the .publisher attribute of the .instance wrapped in the form, not the form itself, so:
#login_required
def Publish(request):
if request.method == 'POST':
form = CreatePostForm(request.POST,request.FILES)
if form.is_valid():
form.instance.publisher = request.user
form.save()
return redirect('home')
else:
form = CreatePostForm()
return render(request,'posts/publish.html',{
'form': form,
})
Since you are submitting both files and data, you should specify the enctype=… attribute [mdn] in the <form>:
<form enctype="multipart/form-data" method="POST">
…
</form>
Note: Django's DateTimeField [Django-doc]
has a auto_now_add=… parameter [Django-doc]
to work with timestamps. This will automatically assign the current datetime
when creating the object, and mark it as non-editable (editable=False), such
that it does not appear in ModelForms by default.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Related
I am trying to build a simple user registration page. I want it to include a captcha for validation purposes. I am using django-simple-captcha for this purpose. (If there's a better library, tell me...)
So far everything is working great, EXCEPT that when a captcha is incorrect the user is not notified--they are simply returned to the registration screen. How can I get a specific ValidationError message printed when the captcha is invalid? (I'm also using django-crispy-forms, if that makes any difference)
template:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Registration</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Already Have An Account?<a class="ml-2" href="{% url 'login' %}">Log in</a></small>
</div>
</div>
{% endblock content %}
form model:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2'] # including 'captcha here didn't seem to make a difference
and the view:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
*do unrelated things*
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'register-template-url', {'form': form})
from simplecaptcha.fields import CaptchaField----
if you are importing CaptchaField like this it will work. If it not works just simply do 1 change as shown below
from simplecaptcha import captcha,captchaform
#captchaform('captcha')
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2','captcha']
I am trying to create a student register page that allows the student to upload a profile photo. I am using Django User model and a StudentProfile model that has a OneToOne relation with User. Here are my codes:
student\models.py:
from django.db import models
from django.contrib.auth.models import User
class StudentProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,)
avatar = models.ImageField(upload_to='student_profile/', null=True, blank=True)
def __str__(self):
return self.user.username
students/form.py:
from django import forms
class ImageUploadForm(forms.Form):
profile_photo = forms.ImageField()
eLearning/views.py:
from django.contrib.auth import authenticate, login, get_user_model
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import LoginForm, RegisterForm
from students.forms import ImageUploadForm
from students.models import StudentProfile
User = get_user_model()
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
if register_form.is_valid():
# print(register_form.cleaned_data)
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
if photo_upload_form.is_valid():
user = username
avatar = photo_upload_form.cleaned_data.get("profile_photo")
new_user_profile = StudentProfile.objects.create(user, avatar)
print(new_user)
return render(request, "auth/register.html", context)
auth/register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
<div class="col-5">
<form method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
<input id="id_image" type="file" class="my-2" name="image">
{{ photo_upload_form|crispy }}
</form>
</div>
</div>
</div>
{% endblock %}
I am facing 2 problems:
1) The ImageUploadForm is not rendering on to register.html
2) A StudentProfile is not being created. User is being created fine.
I also tried replacing form with ModelForm for ImageUploadForm but I get a NULL constraint for student_user since Django doesn't what user for StudentProfile is.
I have been looking through Stack Overflow. All solutions are about how to upload a user image to Django admin but I haven't found anything that shows how to associate the uploaded image to User model during registration. Forgive me if this is a repeated question. Thanks.
In your eLearning/views.py:
the context you are passing to the html page the _ is missing
context = {
"register_form": register_form,
"photo_upload form": photo_upload_form
}
This will be the reason for the ImageUploadForm is not rendering on to register.html
It's should be like
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
So I figured it out. The real issue was with the register.html code. The submit button only worked for the register_form so the photo upload form was not validating, hence student profile entry was not being created. Here's the updated code:
eLearning/views.py:
from students.forms import ImageUploadForm
from students.views import upload_pic
def register_page(request):
register_form = RegisterForm(request.POST or None)
photo_upload_form = ImageUploadForm(request.POST, request.FILES)
context = {
"register_form": register_form,
"photo_upload_form": photo_upload_form
}
if register_form.is_valid():
username = register_form.cleaned_data.get("username")
first_name = register_form.cleaned_data.get("first_name")
last_name = register_form.cleaned_data.get("last_name")
email = register_form.cleaned_data.get("email")
password = register_form.cleaned_data.get("password")
new_user = User.objects.create_user(
username, email, password,
first_name=first_name,
last_name=last_name,
)
upload_pic(request, photo_upload_form, username=username)
return render(request, "auth/register.html", context)
students/views.py:
from django.contrib.auth import get_user_model
from django.http import HttpResponseRedirect
from django.shortcuts import render, redirect, HttpResponse
from .models import StudentProfile
from .forms import ImageUploadForm
def upload_pic(request, form, username):
if request.method == 'POST':
if form.is_valid():
User = get_user_model()
user = User.objects.get(username=username)
avatar = form.cleaned_data.get('profile_photo')
new_user_profile = StudentProfile.objects.create(user=user, avatar=avatar)
new_user_profile.save()
register.html:
{% extends "base.html" %}
{% load static %}
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row my-4">
<div class="col-5">
<form action="" method="post" enctype="multipart/form-data" class="form-control">
{% csrf_token %}
{{ register_form|crispy }}
{{ photo_upload_form|crispy }}
<input type="submit" class="btn btn-default" value="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
You have to make sure enctype="multipart/form-data" is inside your tags or the image upload form will not get validated. I would also recommend adding an image validation method to your form.py. Something Sachin pointed out earlier: image form and validation. Hope this helps.
I have designed a model in Django and a form according to it. The below are the both files.
models.py
from django.db import models
class TotalEvent(models.Model):
CustomerID = models.CharField(max_length=30)
eventID = models.CharField(max_length=100)
eventPlace = models.CharField(max_length=100)
eventStartTime = models.TimeField(auto_now=False)
eventDate = models.DateField(auto_now=False)
forms.py
from django import forms
from django.forms import ModelForm
from catering.models import TotalEvent
class TotalEventForm(ModelForm):
class Meta:
model = TotalEvent
fields = '__all__'
Now, When in my html file I tried this:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Detail page</h1>
<p>Enter your schedule details here</p>
<form method="post">{% csrf_token %}
{% for field in forms %}
{{field}}
<input type="submit" value="Submit"/>
{% endfor %}
</form>
{% endblock %}
views.py
from django.shortcuts import render
from catering.forms import TotalEvent
def add(request):
if request.method == 'POST':
form = TotalEvent(request.POST)
if form.is_valid():
form.save()
return render(request, 'index.html', { 'form': TotalEvent()
})
In the output it shows no input fields except the following output
Enter your schedule details here
Please have a look and let me know where is the error.
Use TotalEventForm instead TotalEvent as TotalEvent is model class not form class, update your views.py
def add(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = TotalEventForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = TotalEventForm()
return render(request, 'index.html', {'form': form})
and you can use form directly in your html file.
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit"/>
</form>
type
{% for field in form %}
instead of
{% for field in forms %}
I am working on my first django app. I am building an app that allows the user to rate beer. I want my user to be able to edit an entry they've already created. I take them to a ModelForm, and ask for their entry. When the POST method is called, my data is invalid. Here is my model.py:
from django.db import models
class Rating(models.Model):
beer_name = models.TextField()
score = models.DecimalField(max_digits=2, decimal_places=1)
notes = models.TextField(blank=True)
brewer = models.TextField(blank=True)
and forms.py:
from django import forms
from ratings.models import Rating
class RatingForm(forms.ModelForm):
class Meta:
model = Rating
fields = ['beer_name', 'score', 'notes', 'brewer']
Here is the views.py of my edit function:
def edit(request, row_id):
rating = get_object_or_404(Rating, pk=row_id)
if request.method == "POST":
form = RatingForm(request.POST, instance=rating)
if form.is_valid():
form.save()
return redirect(home)
else:
return HttpResponse("Invalid entry.")
else:
context = {'form': rating}
form = RatingForm(instance=rating)
return render(
request,
'ratings/entry_def.html',
context
)
However, every time the POST is called I get an "Invalid entry." HttpResponse, meaning my form.is_valid() is being returned False. Here is my template:
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Edit Rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: <textarea>{{ form.beer_name }}</textarea></p>
<p>Score: <input type="text" name="BeerScore" value="{{ form.score }}"></p>
<p>Notes: <textarea>{{ form.notes }}</textarea></p>
<p>Brewer: <textarea>{{ form.brewer }}</textarea></p>
<p><button type="submit" class="save btn btn-primary">Save</button></p>
<p><button type="reset" class="btn btn-primary">Cancel</button></p>
</form>
</div>
</div>
</div>
{% endblock %}
So when I press my Save button, I am getting the response. Here is my edit url in urls.py:
urlpatterns = [
...
url(r'rating/edit/(?P<row_id>[0-9]+)/$', edit , name='rating-edit'),
]
You're wrapping fields in other fields which don't have name attributes. This is most likely causing the values to be excluded from the request.POST data.
Additionally, Django form fields all have a corresponding HTML widget. So there's really no need to render the HTML by hand, unless you need to.
Change your template code to:
<p>
{{ form.beer_name.label }}: {{ form.beer_name }}
{% if form.beer_name.errors %}
<br />{{ form.beer_name.errors }}
{% endif %}{# repeat for other fields as needed #}
</p>
<p>{{ form.score.label }}: {{ form.score }}</p>
<p>{{ form.notes.label }}: {{ form.notes }}</p>
<p>{{ form.brewer.label }}: {{ form.brewer }}</p>
<p><button type="submit" class="save btn btn-primary">Save</button></p>
<p><button type="reset" class="btn btn-primary">Cancel</button></p>
If you need to change the widget, do so at the form class level:
class RatingForm(forms.ModelForm):
class Meta:
model = Rating
def __init__(self, *args, **kwargs):
super(RatingForm, self).__init__(*args, **kwargs)
self.fields['notes'].widget = forms.Textarea()
This way, Django manages the attributes and binding for you.
Your view can also use some cleanup:
def edit(request, row_id):
rating = get_object_or_404(Rating, pk=row_id)
form = RatingForm(request.POST or None, instance=rating)
if request.method == "POST" and form.is_valid():
form.save()
return redirect(home)
context = {'form': rating}
return render(request, 'ratings/entry_def.html', context)
Hi guys I am new to Django.
I wants that when I login to my account there is a edit button which shows me a form of some fields which I can edit.
I am confused how the data is saved to the same user profile.
So can anybody tell me how is that possible.Can show me it with one example
With my profile.html I can see my profile and on click on edit button I can edit my profile
{% extends 'base.html' %}
{% block content %}
<p>User_id: {{ drinker.user_id }}
<p>Name: {{ drinker.name }}</p>
<p>Birthday: {{ drinker.birthday }}</p>
<p>first_name: {{ user.first_name }}</p>
<p>Users: {{ user.username }}</p>
<p>Edit Profile
{% endblock %}
Edit function
def Edit(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
drinker = request.user.get_profile()
context = {'drinker':drinker}
return render_to_response('edit.html', context, context_instance=RequestContext(request))
**Edit.html**
{% extends "base.html" %}
{% block extrahead %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js" type="text/javascript"></script>
<script>
$(function() {
$( "#birth" ).datepicker();
});
</script>
{% endblock %}
{% block content %}
<form action="/edit1/" method="post">
{% csrf_token %}
<div class="register_div">
<p><label for="name">Name:</label></p>
<p><input type="text" value="{{ drinker.name }}"></p>
</div>
<div class="register_div">
<p><label for="birthday">Birthday: {{ drinker.birthday }} </label></p>
<p>Choose new date of birth</p>
<p><input type="text" value="" id="birth"></p>
</div>
<p><input type="submit" value="submit" /></p>
</form>
{% endblock %}
On edit1 edit request function works
def EditRequest(request):
#if request.method == 'POST':
#form = UserProfileForm(request.POST, instance=user)
#if request.user.is_authenticated():
#return render_to_response('hgdhg')
if request.method == 'POST':
form = EditForm(request.POST)
if form.is_valid():
user=User.objects.create_user(usere_id=form.cleaned_data['user_id'])
#user.save()
drinker=user.get_profile()
drinker.name=form.cleaned_data['name']
drinker.birthday=form.cleaned_data['birthday']
drinker.save()
return HttpResponseRedirect('/profile/')
else:
return HttpResponseRedirect('/f/')
else:
return render_to_response('f')#,{'form':form} , context_instance=RequestContext(request))
this editrequest doesn't work ?
Here are the steps you need to execute to edit a user's profile:
Find out which user is logged in (read up on user authentication)
Check if the user has a profile or not; use the normal django query mechanism for that.
If the user has a profile; populate a ModelForm with the instance of the profile (see this page in the manual)
Display the form to the end user just like any other form.
When the user submits changes, do the normal form validation and save the object to the database.
Here is some code that does steps 1-4:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from myapp.models import UserProfile
from myapp.forms import UserProfileForm
#login_required
def edit_profile(request):
try:
user_profile = UserProfile.objects.get(user=request.user)
except UserProfile.DoesNotExist:
# this user has no profile
return redirect('/error')
user_profile_form = UserProfileForm(instance=user_profile)
return render(request,'profile_edit.html',{'form':user_profile_form})
The UserProfileForm class:
from django import forms
from myapp.models import UserProfile
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
pass the instance of user along your model form
user = User.objects.get(user_name = username)
form = Registrationform(instance=user)
and render this form to your template
Example i did before:
#login_required
def lexuseditform(request,userpk):
if Adult.objects.filter(user=request.user).exists():
adult = Adult.objects.get(user=request.user) # load existing Adult
else:
adult = Adult(user=request.user) # create new Adult
if request.method == 'POST': # If the form has been submitted...
form = AdultForm(request.POST,instance=adult) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
redirect_url = reverse('lexusedited',kwargs={'userpk': request.user.pk})
return HttpResponseRedirect(redirect_url) # Redirect after POST
else:
form = AdultForm(instance=adult) # An unbound form
return render(request,'lexus/lexuseditform.html', {'form': form})
#login_required
def lexusedited(request,userpk):
return render(request,'lexus/lexusedited.html')
Hope this helps...