我是Django的新手,正在编写我的第一个应用程序。这很简单,您可以使用表单添加新的“客户端”。其中一个字段是ImageField,在输入图像和提交表单后,图像消失,并且与该客户端无关。
我尝试过使用request.FILES命令,但似乎没有任何效果,并且已将enctype =“multipart / form-data”添加到html页面。
forms.py
from django import forms
from django.contrib.auth.models import User
from address_book.models import Client, UserProfile
class ClientForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="Name: ")
phone = forms.IntegerField(help_text="Phone Number: ")
address = forms.CharField(max_length=128, help_text="Address: ", required=False)
desired_weight = forms.IntegerField(help_text="Desired Weight: ")
picture = forms.ImageField(help_text="Upload image: ", required=False)
start_weight = forms.IntegerField(help_text="Start Weight: ")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput(), required=False)
comments = forms.CharField(max_length=500, help_text="Comments: ", required=False)
# An inline class to provide additional information on the form.
class Meta:
# Provide an association between the ModelForm and a model
model = Client
fields = ('name', 'phone', 'address', 'desired_weight', 'start_weight', 'picture',)
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('nickname',)
# fields = ('website', 'picture')
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from address_book.forms import ClientForm, UserForm, UserProfileForm
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from address_book.models import Client
def index(request):
client_list = Client.objects.all().order_by('name')
# Construct a dictionary to pass to the template engine as its context.
# Note the key boldmessage is the same as {{ boldmessage }} in the template!
context_dict = {'clients': client_list}
# Return a rendered response to send to the client.
# We make use of the shortcut function to make our lives easier.
# Note that the first parameter is the template we wish to use.
return render(request, 'address_book/index.html', context_dict)
def add_client(request):
# A HTTP POST?
if request.method == 'POST':
form = ClientForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save(commit=True)
# Now call the index() view.
# The user will be shown the homepage.
if 'picture' in request.FILES:
form.picture =request.FILES['picture']
form.save()
return index(request)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = ClientForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'address_book/add_client.html', {'form': form})
def client(request, client_name_slug):
# Create a context dictionary which we can pass to the template rendering engine.
context_dict = {}
try:
# Can we find a category name slug with the given name?
# If we can't, the .get() method raises a DoesNotExist exception.
# So the .get() method returns one model instance or raises an exception.
client = Client.objects.get(slug=client_name_slug)
context_dict['client_name'] = client.name
context_dict['client_name_slug'] = client_name_slug
context_dict['client_phone'] = client.phone
context_dict['client_address'] = client.address
context_dict['desired_weight'] = client.desired_weight
context_dict['start_weight'] = client.start_weight
context_dict['comments'] = client.comments
context_dict['picture'] = client.picture
# Retrieve all of the associated pages.
# Note that filter returns >= 1 model instance.
# pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
# context_dict['pages'] = pages
# We also add the category object from the database to the context dictionary.
# We'll use this in the template to verify that the category exists.
context_dict['client'] = client
except Client.DoesNotExist:
# We get here if we didn't find the specified category.
# Don't do anything - the template displays the "no category" message for us.
pass
# Go render the response and return it to the client.
print context_dict
return render(request, 'address_book/client.html', context_dict)
def register(request):
# A boolean value for telling the template whether the registration was successful.
# Set to False initially. Code changes value to True when registration succeeds.
registered = False
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
# Note that we make use of both UserForm and UserProfileForm.
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
# If the two forms are valid...
if user_form.is_valid() and profile_form.is_valid():
# Save the user's form data to the database.
user = user_form.save()
# Now we hash the password with the set_password method.
# Once hashed, we can update the user object.
user.set_password(user.password)
user.save()
# Now sort out the UserProfile instance.
# Since we need to set the user attribute ourselves, we set commit=False.
# This delays saving the model until we're ready to avoid integrity problems.
profile = profile_form.save(commit=False)
profile.user = user
# Did the user provide a profile picture?
# If so, we need to get it from the input form and put it in the UserProfile model.
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
# Now we save the UserProfile model instance.
profile.save()
# Update our variable to tell the template registration was successful.
registered = True
# Invalid form or forms - mistakes or something else?
# Print problems to the terminal.
# They'll also be shown to the user.
else:
print user_form.errors, profile_form.errors
# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()
profile_form = UserProfileForm()
# Render the template depending on the context.
return render(request,
'address_book/register.html',
{'user_form': user_form, 'profile_form': profile_form, 'registered': registered} )
def user_login(request):
# If the request is a HTTP POST, try to pull out the relevant information.
if request.method == 'POST':
# Gather the username and password provided by the user.
# This information is obtained from the login form.
username = request.POST['username']
password = request.POST['password']
# Use Django's machinery to attempt to see if the username/password
# combination is valid - a User object is returned if it is.
user = authenticate(username=username, password=password)
# If we have a User object, the details are correct.
# If None (Python's way of representing the absence of a value), no user
# with matching credentials was found.
if user:
# Is the account active? It could have been disabled.
if user.is_active:
# If the account is valid and active, we can log the user in.
# We'll send the user back to the homepage.
login(request, user)
return HttpResponseRedirect('/address_book/')
else:
# An inactive account was used - no logging in!
return HttpResponse("Your 3010 account is disabled.")
else:
# Bad login details were provided. So we can't log the user in.
print "Invalid login details: {0}, {1}".format(username, password)
return HttpResponse("Invalid login details supplied.")
# The request is not a HTTP POST, so display the login form.
# This scenario would most likely be a HTTP GET.
else:
# No context variables to pass to the template system, hence the
# blank dictionary object...
return render(request, 'address_book/login.html', {})
@login_required
def user_logout(request):
# Since we know the user is logged in, we can now just log them out.
logout(request)
# Take the user back to the homepage.
return HttpResponseRedirect('/address_book/')
models.py
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Client(models.Model):
name = models.CharField(max_length=128, unique=True)
phone = models.IntegerField(default=0)
desired_weight = models.IntegerField(default=0)
start_weight = models.IntegerField(default=0)
picture = models.ImageField(upload_to='/address_book/profile_pics', blank=True)
address = models.CharField(max_length=128, blank=True)
comments = models.CharField(max_length=500, blank=True)
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Client, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
# website = models.URLField(blank=True)
nickname = models.CharField(max_length=20, blank=True)
# picture = models.ImageField(upload_to='profile_images', blank=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
add_client.html
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}Add a Client{% endblock %}
{% block body_block %}
<h1>Add a Client</h1>
<form id="ClientForm" method="post" action="/address_book/add_client/" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
<br />
<br />
{% endfor %}
<input type="submit" name="submit" value="Create Client" />
</form>
{% endblock %}
client.html
{% extends 'base.html' %}
{% load staticfiles %}
{% load easy_maps_tags %}
{% load addressbook_extras %}
{% block title %}{{ client_name }}{% endblock %}
{% block body_block %}
<h1>{{ client_name }}</h1>
<li>Phone: {{ client_phone }} </li>
<li>Address: {{ client_address }} </li>
<li>Start Weight: {{ start_weight }} </li>
<li> Desired Weight: {{ desired_weight }} </li>
<li> Comments: {{ comments }} </li>
{% if picture %}
<img src="{ picture }" alt="Client Photo">
{% else %}
<li> No image uploaded </li>
{% endif %}
{% if client_address|address_test != None %}
{% easy_map client_address 400 400 %}
{% else %}
<strong> Invalid address </strong>
{% endif %}
{% endblock %}
base.html文件
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Address Book</title>
</head>
{% if user.is_authenticated %}
<h1>Hello {{ user.username }}!</h1>
{% else %}
<h1>Please login below</h1>
{% endif %}
<body>
{% block body_block %}{% endblock %}
</body>
<h2> Need to make changes? </h2>
<ul>
<li><a href="{% url 'index' %}">Go home</a></li>
{% if user.is_authenticated %}
<li><a href="{% url 'logout' %}">Logout</a></li>
<li><a href="{% url 'add_client' %}">Add new client</a></li>
{% else %}
<li><a href="{% url 'login' %}">Login</a></li>
<li><a href="{% url 'register' %}">Register here</a></li>
{% endif %}
</ul>
</html>
答案 0 :(得分:1)
我似乎忘记将request.FILES传递给您的表单。
试试这个:
if request.method == 'POST':
form = ClientForm(request.POST, request.FILES)
以下是使用django上传文件的绝佳示例: Need a minimal Django file upload example
答案 1 :(得分:0)
您的错误在这里:
<img src="{ picture }" alt="Client Photo">
您应该使用双括号和 url()
方法,如下所示:
<img src="{{ picture.url }}" alt="Client Photo">
ImageField
已延长FieldFile
,您可以使用url() method访问相对网址