2015-07-23 3 views
2

Наверху моя форма для отправки предложения правильно отображается, и при отправке предложений у меня нет ошибки, они не сохраняются в моей базе данных. Я знаю, что, проверяя админ-сайт, объекты не сохраняются. Но, с другой стороны, я уже написал код для регистрации, и пользователи сохраняются в базе данных.Django: форма не сохраняется в моей базе данных

Я подозреваю, что отношение 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) 

Все другие функции работы (регистрации и входа) и функция регистра() правильно избавляет пользователя, но функцию send_offer(), которая очень похож на регистрационную функцию, не работает и после поиска в Интернете в течение нескольких часов, я до сих пор не знаю, почему предложения не сохраняются.

Но когда я пытаюсь добавить предложение на сайт администратора, оно работает.

Кроме того, я пытался сохранить предложение в питон manage.py оболочки:

>>> 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' 

EDIT: Решение было добавить следующие строки:

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.

+0

Не знаю, если это решит вашу проблему, но вы забыли о закрытии '' тег в шаблоне. – Leistungsabfall

+0

К сожалению, нет. Но это была ошибка. – Cobblepot

+0

, чтобы быть уверенным - можете ли вы поместить печать прямо над «offerform.save()» и убедиться, что ее вызвали? –

ответ

3

В ModelForm, если вы не передадите какой-либо объект при его создании. Он создаст новый объект в базе данных указанного типа. Таким образом, в этом случае на вашем SendOfferForm вы указали Предложение. Если вы передаете существующий объект, он должен быть указанным типом в этом случае.

Похоже, вы пытаетесь автоматически заполнить поле издателя зарегистрированным в данный момент пользователем. Для этого вам нужно вручную установить поле издателя в экземпляр пользователя.

Если вы собираетесь в форме, чтобы создать новое предложение в базе данных это сделать

offerform = SendOfferForm(request.POST) 

Если вы пытаетесь обновить текущее предложение, то вам нужно будет передать объект экземпляра в виде

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

Чтобы вручную добавить запрос полевого пользователя в свою форму с помощью commit = False, это вернет объект предложения БЕЗ сохранения в БД.На этом этапе у вас есть возможность настроить данные в объекте и затем сохранить.

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

Все это объясняется более подробно в Джанго документации ModelForm documentation

+0

Я не уверен, что понимаю. Вы имеете в виду, я должен написать что-то подобное в views.py: Offer_publisher = logged_in_user.username offerform = SendOfferForm (request.POST, экземпляр = Offer_publisher) вместо: offerform = SendOfferForm (request.POST, экземпляр = logged_user)? – Cobblepot

+0

Да modelform нуждается в экземпляре объекта, который он представляет. Вы должны установить fk feild вручную, если вы не разрешаете редактировать feild пользователем в форме. – Roge

+0

нет, это еще хуже. я получил ошибку: AttributeError в/объекте envoyer_une_offre «» STR не имеет атрибута «_meta» Я просто положить издатель = logged_user.username в начале моей функции, а затем я написал offerform = SendOfferForm (запрос .POST, instance = publisher) – Cobblepot