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

Cob*_*pot 2 django foreign-keys django-models django-1.8

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

我怀疑我的两个模型之间的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
Run Code Online (Sandbox Code Playgroud)

表格

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',)
Run Code Online (Sandbox Code Playgroud)

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())
Run Code Online (Sandbox Code Playgroud)

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'),
    )
Run Code Online (Sandbox Code Playgroud)

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 %}
Run Code Online (Sandbox Code Playgroud)

管理员

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)
Run Code Online (Sandbox Code Playgroud)

其他所有功能(注册和登录)均起作用,register()函数可正确保存用户,但send_offer()函数非常类似于register函数不起作用,并且在互联网上搜索了数小时后,我仍然不知道为什么不保存报价。

但是,当我尝试在管理站点中添加报价时,它似乎可以正常工作。

此外,我尝试将要约保存在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'
Run Code Online (Sandbox Code Playgroud)

编辑:解决方案是添加以下行:

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

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

Rog*_*oge 5

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

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

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

offerform = SendOfferForm(request.POST)
Run Code Online (Sandbox Code Playgroud)

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

offerform = SendOfferForm(request.POST, instance=someOffer)
Run Code Online (Sandbox Code Playgroud)

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

offer = offerform.save(commit=False)
offer.publisher = request.user.id
offer.save()
Run Code Online (Sandbox Code Playgroud)

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