13 votes

Impossible d'assigner doit être une instance. Django

J'ai essayé de créer un projet django qui a des utilisateurs et ces utilisateurs peuvent ajouter des titres de livres qu'ils ont créés. Mais à chaque fois que je saisis un titre de livre (pas sur la page d'administration), j'obtiens cette erreur

Cannot assign "u'Hello Wold'": "Scripter.title" must be a "Book" instance.

models.py

from django.db import models
from django.contrib.auth.models import User

class Book(models.Model):
    script_title = models.CharField(max_length=100)

    def __unicode__(self):
        return self.script_title

class Scripter(models.Model):
    user = models.OneToOneField(User)
    name = models.CharField(max_length=30)
    title = models.ForeignKey(Book, null=True, blank=True, default=None)

    def __unicode__(self):
        return self.name

forms.py

from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from scripters.models import Scripter#, Book

class RegistrationForm(ModelForm):
    username = forms.CharField(label=(u'User Name'))
    email = forms.EmailField(label=(u'Email Address'))
    password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
    password1 = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))

    class Meta:
        model = Scripter
        exclude = ('user','title')

    def clean_username(self):
        username = self.cleaned_data['username']
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            return username
        raise forms.ValidationError("User Name has been taken!")

    def clean(self):
        if self.cleaned_data['password'] != self.cleaned_data['password1']:
            raise forms.ValidationError("The passwords did not match")
        else:
            return self.cleaned_data

class LoginForm(forms.Form):
    username = forms.CharField(label=(u'Username'))
    password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))

class CreateScript(ModelForm):
    title = forms.CharField(label=(u'Script Title'))

    class Meta:
        model = Scripter
        exclude = ('user','name',)

    def clean_title(self):
        title = self.cleaned_data['title']
        return title

vues.py

from django.http import HttpResponseRedirect
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.shortcuts import render_to_response
from django.template import RequestContext
from scripters.forms import RegistrationForm, LoginForm, CreateScript
from scripters.models import Scripter, Book
from django.contrib.auth import authenticate, login, logout

def ScripterRegistration(request):
    if request.user.is_authenticated():
        return HttpResponseRedirect('/profile/')
    if request.method =='POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():
            user = User.objects.create_user(username=form.cleaned_data['username'],
                email = form.cleaned_data['email'],
                password = form.cleaned_data['password']
            )
            user.save()
            scripter = Scripter(user=user, name=form.cleaned_data['name'])
            scripter.save()

            return HttpResponseRedirect('/profile/')
        else:
            return render_to_response('index.html', {'form': form}, context_instance=RequestContext(request))
    else:
        form = RegistrationForm()
        context = {'form': form}
        return render_to_response('index.html', context, context_instance=RequestContext(request))

@login_required
def Profile(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/')
    Scripter = request.user.get_profile()

    context = {'Scripter': Scripter, 'Book': Book}
    return render_to_response('profile.html', context, context_instance=RequestContext(request))

def LoginRequest(request):
    if request.user.is_authenticated():
        return HttpResponseRedirect('/profile/')
    if request.method == 'POST':
        submit = LoginForm(request.POST)
        if submit.is_valid():
            username = submit.cleaned_data['username']
            password = submit.cleaned_data['password']
            scripter = authenticate(username=username, password=password)
            if scripter is not None:
                login(request, scripter)
                return HttpResponseRedirect('/profile/')
            else:
                return HttpResponseRedirect('/login/')
    else:
        submit = LoginForm()
        context = {'submit': submit}
        return render_to_response('login.html',context, context_instance=RequestContext(request))

def LogoutRequest(request):
    logout(request)
    return HttpResponseRedirect('/login/')

@login_required
def NewScript(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/')
    if request.method =='POST':
        title_form = CreateScript(request.POST)
        if title_form.is_valid():
            new_script = Book.objects.get_or_create(
                script_title = title_form.cleaned_data['title']
            )
            new_script.save()
            script = Book(script_title=title_form.cleaned_data['title'])
            script.save()
            return HttpResponseRedirect('/edit/')
        else:
            return render_to_response('NewScript.html', {'title_form': title_form}, context_instance=RequestContext(request))
    else:
        title_form = CreateScript()
        context = {'title_form': title_form}
        return render_to_response('NewScript.html', context, context_instance=RequestContext(request))

14voto

Chris Pratt Points 53859

Bien sûr. Je ne sais pas où est la confusion ici. Scripter.title est une clé étrangère à Book donc vous devez lui donner un véritable Book et non une chaîne.

8voto

Marcin Kulus Points 353

D'abord, bien que ce ne soit pas votre question, je crois que vous avez manqué quelque chose. Si je comprends bien, vous souhaitez que les scripteurs puissent avoir plusieurs livres. Or, avec vos modèles, ils ne peuvent avoir qu'un seul livre. Si je suis correct quant à ce que vous essayez d'obtenir, votre modèle devrait plutôt ressembler à ceci :

class Book(models.Model):
  script_title = models.CharField(max_length=100)
  scripter = models.ForeignKey(Scripter)#A book "remembers" who wrote it

  def __unicode__(self):
    return self.script_title

class Scripter(models.Model):
  user = models.OneToOneField(User)
  name = models.CharField(max_length=30)
  #Scripter can write multiple books, can't he? So the next line is removed,
  #replaced by an extra line in Book class

  # title = models.ForeignKey(Book, null=True, blank=True, default=None)

Vous accéderez alors aux livres de Scripter comme ceci :

scripter = Scripter.objects.get(name="joshua")
books = scripter.book_set.all() #all books written by joshua

Pour répondre à votre question, dans la forme actuelle, vous devriez faire quelque chose comme ceci :

book = Book.objects.get(script_title="some_title")
scripter.title = book

Mais comme je l'ai déjà dit, vous devez changer la structure de votre modèle, donc vous allez plutôt le faire :

scripter = Scripter.objects.get(name="joshua")
book = Book.objects.Create(script_title="some title",scripter=scripter)

0voto

user12832372 Points 17

Vous n'avez pas de clé primaire dans votre modèle de livre

    class Book(models.Model):
script_title = models.CharField(primary_key = True,max_length=100)

def __unicode__(self):
    return self.script_title

Cela devrait fonctionner

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X