Django:表单没有保存到我的数据库中

时间:2015-07-23 13:45:10

标签: django django-models foreign-keys django-1.8

Altough我的表单发送报价已正确显示,我提交报价时没有错误,它们没有保存在我的数据库中。 我知道通过检查管理站点,没有保存任何对象。 但另一方面,我已经编写了注册代码,用户也保存在数据库中。

我怀疑我的两个模型之间的ForeignKey关系是罪魁祸首。

models.py

from django.db import models

class User(models.Model):

username = models.CharField(max_length=30, unique=True, blank=False)
password1 = models.CharField(max_length=40, blank=False)
password2 = models.CharField(max_length=40, blank=False)
mail = models.EmailField(unique=True, blank=False)
birthday = models.DateField(blank=False)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date d'inscription")
def __str__(self):
    return self.username 

class Offer(models.Model):

publisher = models.ForeignKey(User)
content = models.TextField()
date = models.DateTimeField(auto_now_add=True, auto_now=False,    verbose_name="Date de parution")

def __str__(self):
    return self.publisher.username

forms.py

from django import forms
from django.contrib import admin
from django.contrib.auth.hashers import make_password, check_password
from django.utils.translation import ugettext_lazy as _
from myuser.models import User, Offer

class UserCreationForm(forms.ModelForm):
    class Meta:
        model = User
        widgets = {
        'password1' : forms.PasswordInput(),
        'password2' : forms.PasswordInput(),
        }
        fields = ("username", "password1", "password2", "mail")

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("les mots de passes ne correspondent pas")
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserCreationForm, self).save(commit=False)
        user.password1 = make_password(self.cleaned_data["password1"])
        user.password2 = make_password(self.cleaned_data["password2"])
        if commit:
            user.save()
        return user

class LoginForm(forms.Form):
    username = forms.CharField(label="nom d'utilisateur")
    password = forms.CharField(label="mot de passe",
                                widget = forms.PasswordInput)
    def clean(self):
        cleaned_data = super(LoginForm, self).clean()
        username = cleaned_data.get('username')
        password = cleaned_data.get('password')
        user = User.objects.get(username=username)
        if check_password(password, user.password1):
            return cleaned_data
        else:
            raise forms.ValidationError("Le nom d'utilisateur et le mot de passe ne correspondent pas")

class SendOfferForm(forms.ModelForm):
    class Meta:
        model = Offer
        fields = ('content',)

Views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.exceptions import ObjectDoesNotExist

from myuser.models import User, Offer
from myuser.forms import UserCreationForm, LoginForm, SendOfferForm

def get_logged_user_from_request(request):
    if 'logged_user_id' in request.session:
        logged_user_id = request.session['logged_user_id']
        return User.objects.get(id=logged_user_id)
    else:
        return None

def register(request):
    registered = False
    if request.method == 'POST':
        user_form = UserCreationForm(data=request.POST)
        if user_form.is_valid():
            user = user_form.save()
            registered = True
        else:
            print(user_form.errors)
    else:
        user_form = UserCreationForm()
    return render(request,
           'myuser/create_account.html',
           {'user_form': user_form, 'registered': registered} )

def login(request):
    if request.method=='POST':
        form = LoginForm(request.POST)
        try:
            if form.is_valid():
               user = User.objects.get(username=request.POST.get('username')) 
               logged_user = User.objects.get(username=request.POST.get('username'))
               request.session['logged_user_id'] = logged_user.id
               return HttpResponseRedirect('/')
            else:
                error = "le nom d'utilisateur et le mot de passe ne correspondent pas"
                return HttpResponse("Invalid login details supplied.")
        except User.DoesNotExist:
            return HttpResponse("Invalid login details supplied.")
    else:
        form = LoginForm
    return render(request, 'myuser/mylogin.html', locals())



def send_offer(request):
    sent = False
    logged_user = get_logged_user_from_request(request)
    if logged_user:
        if request.method == 'POST':
            try:
                offerform = SendOfferForm(request.POST, instance=logged_user)
                if offerform.is_valid():        
                    sent = True
                    offerform.save()
                else:
                    print(offerform.errors)
            except:
                return HttpResponse("drapeau except")
        else:
            offerform = SendOfferForm(instance=logged_user)
    else:
        return HttpResponse("Vous n'êtes pas connecté")
    return render(request, 'myuser/send_offer.html', locals())

urls.py

from django.conf.urls import patterns, url, include
from django.views.generic import TemplateView

urlpatterns = patterns('myuser.views',
    url(r'^inscription/$', 'register',  name='create_account'),
    url(r'^connexion/$', 'login', name='login'),
    url(r'^envoyer_une_offre$', 'send_offer', name='send_offer'),
    )

send_offer.html

{% extends "base.html" %}
{% block content %}

<h1> Offer </h1>

{% if not sent %}
<p> write your offer <p/>

    <form action="{% url "send_offer" %}" method='POST' class='sendofferform'>
        {{ form.errors }}
        {{ form.non_field_errors }}
        {% csrf_token %}
        {{ offerform.as_p }}
        <input type="submit" value="Submit" />
    </form>
{% else %}
Offer is published
<a href="/poster_une_offre">publish another offer?</a><br /> 
<a href="/">get back to the homepage</a><br />
{% endif %}
{% endblock %}

admin.py

from django.contrib import admin
from myuser.models import User, Offer#, Message

class UserAdmin(admin.ModelAdmin):
    list_display = ('id', 'username', 'status', 'college', 'apercu_description')
    list_filter = ('id', 'username', 'birthday')
    date_hierarchy = 'date'
    ordering = ('date', )
    search_fields = ('username', 'description')

    def apercu_description(self, User):

        text = User.description[0:40]
        if len(User.description) > 40:
            return '%s' % text
        else:
            return text

class OfferAdmin(admin.ModelAdmin):
    list_display = ('id', 'publisher', 'apercu_offre')
    list_filter = ('id', )
    date_hierarchy = 'date'
    ordering = ('date', )
    search_fields = ('publisher',)

    def apercu_offre(self, Offer):        
        text = Offer.content[0:40]
        if len(Offer.content) > 40:
            return '%s' % text
        else:
            return text

admin.site.register(User, UserAdmin)
admin.site.register(Offer, OfferAdmin)

所有其他功能工作(注册和登录)和register()功能正确保存用户,但send_offer()函数非常类似于寄存器功能不起作用,并在互联网上搜索几个小时,我仍然不知道为什么不保存优惠。

但是当我尝试在管理网站中添加优惠时,它似乎有效。

此外,我试图在python manage.py shell中保存商品:

>>> Offer.publisher = "a"
>>> Offer.content = "lalalala"
>>> Offer.save()
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/shell.py", line 69, in handle
    self.run_shell(shell=options['interface'])
  File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/shell.py", line 61, in run_shell
    raise ImportError
ImportError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.4/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
TypeError: save() missing 1 required positional argument: 'self'

编辑:解决方案是添加这些行:

    if offerform.is_valid():        
        sent = True
        offer = offerform.save(commit=False)
        offer.publisher = User.objects.get(id=logged_user.id)
        offer.save()

请注意,logged_user是一个函数,在view.py。中描述。

1 个答案:

答案 0 :(得分:5)

在ModelForm上,如果在实例化时没有传递任何对象,它将在指定类型的数据库中创建一个新对象。所以在这种情况下你的SendOfferForm你已经指定了Offer。如果你确实传递了一个现有的对象,那么在这种情况下,它必须是指定的类型。

您似乎正在尝试使用当前登录的用户自动填充发布商字段。为此,您需要手动将发布者字段设置为User的实例。

如果您打算让表单在数据库中创建新的商品,请执行此操作

offerform = SendOfferForm(request.POST)

如果您尝试更新当前商品,则需要将实例对象传递到表单

offerform = SendOfferForm(request.POST, instance=someOffer)

要使用commit = False手动添加表单上的用户字段调用save,这将返回一个商品对象,而不保存到DB。此时,您有机会自定义对象中的数据,然后保存。

offer = offerform.save(commit=False)
offer.publisher = request.user.id
offer.save()

所有这些都在django文档中有更详细的解释 ModelForm documentation