Django:将图片上传到表单

时间:2015-02-25 16:51:18

标签: python html django image forms

我是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>

2 个答案:

答案 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访问相对网址