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

Django : form is not saved into my database

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

我怀疑我的 2 个模型之间的外键关系是罪魁祸首。

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 中有描述。

在 ModelForm 上,如果您在实例化时不传递任何对象,它将在指定类型的数据库中创建一个新对象。因此,在本例中,您在 SendOfferForm 上指定了 Offer。如果您确实传递了一个现有对象,在本例中它必须是指定的类型 Offer。

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

如果您打算让表单在数据库中创建一个新报价,请执行此操作

offerform = SendOfferForm(request.POST)

如果您尝试更新当前报价,那么您需要将实例对象传递到表单中

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

要使用 commit=False 在您的表单上手动添加用户字段调用保存,这将 return 提供对象而不保存到数据库。此时你就有机会自定义object中的数据然后保存了。

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

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