2010-09-08 26 views
4

J'essaie de surcharger enregistrer dans le modèle pour ajouter l'utilisateur actuel en tant que propriétaire d'un véhicule. Mais je reçois l'objet 'NoneType' n'a aucun attribut 'user' Qu'est-ce que j'oublie?Comment accéder à la demande dans ModelForm pour ajouter request.user en tant que clé étrangère

forms.py:

class VehicleForm(ModelForm): 
    class Meta: 
     model = Vehicle 
     exclude = ('slug', 'owner',) 

    def __init__(self, *args, **kwargs): 
     self.request = kwargs.pop('request', None) 
     super(VehicleForm, self).__init__(*args, **kwargs) 

    def save(self, *args, **kwargs): 
     kwargs['commit']=False 
     obj = super(VehicleForm, self).save(*args, **kwargs) 
     obj.owner = self.request.user 
     obj.save() 
     return obj 

mon modèle:

class VehicleBase(models.Model): 

    owner   = models.ForeignKey(User) 

    vehicle_type = models.SmallIntegerField(_('kind'), 
        choices=vehicle_types, default=1,) 

    make   = models.CharField(_('make'), max_length=31, 
        help_text=_('Maximum is 31 characters.'),) 

    model   = models.CharField(_('model'), max_length=31, 
        help_text=_('Maximum is 31 characters.'),) 

    class Meta: 
     abstract = True 


class Vehicle(VehicleBase): 
    name  = models.CharField(_('fun name'), max_length=31, 
        help_text=_('Maximum is 31 characters.'),) 

    slug   = models.SlugField(_('slug'),) 

    def save(self, *args, **kwargs): 
     is_new = self.pk is None 
     if is_new: 
      self.slug = slugify("%s %s %s" %(self.make, self.model, self.name,)) 
     super(Vehicle, self).save(*args, **kwargs) # Call the "real" save() method. 

     if is_new: 
      Calendar.objects.get_or_create_calendar_for_object(self, name = "%s's schedule" %self.name) 

    class Meta: 
     unique_together = (("name", "owner",),) 

def __unicode__(self): 
    return u'%s: %s\'s %s %s' %(self.name, self.owner, self.make, self.model,) 

def __str__(self): 
    return self.__unicode__() 

def get_absolute_url(self): 
    return reverse('vehicle_view', kwargs={'object_id':self.id, 'slug':self.slug, },) 

J'utilise une vue générique:

url(r'^create/$', 
    'create_update.create_object', 
    dict(template_name='vehicles/vehicle_create.html', 
     form_class=VehicleForm, 
     post_save_redirect="/vehicles/"), 
    name='vehicle_create'), 
+0

Tu oublies que 'ModelForm' n'a pas d'attribut' request', donc 'self.request' dans votre méthode' 'est save' Aucun » –

+0

@Dominic: voir la méthode '__init__' du formulaire. L'utilisateur définit 'self.request' sur la base de' kwargs'. –

+0

@Manoj - ah, merci. –

Répondre

3

Je voulais ajouter un peu plus d'information à Manoj et de réponses de Daniel. Fondamentalement, je besoin d'une vue personnalisée afin de passer à l'utilisateur sur Enregistrer:

urls.py:

url(r'^create/$', 
    'create_vehicle', 
    name='vehicle_create'), 

views.py:

@login_required 
def create_vehicle(request): 
    if request.method == 'POST': 
     form = VehicleForm(request.POST) 
     if form.is_valid(): 
      vehicle = form.save(commit=False) 
      vehicle.owner = request.user 
      vehicle.save() 
     return HttpResponseRedirect('/vehicles/') 
    else: 
     form = VehicleForm() 
    return render_to_response('vehicles/vehicle_create.html', {'form': form},  context_instance=RequestContext(request)) 

forms.py:

class VehicleForm(ModelForm): 
    class Meta: 
     model = Vehicle 
     exclude = ('slug', 'owner',) 
2

Vous ne montrez pas comment vous êtes instanciation de la forme à votre avis. Il faut se rappeler de passer en fait la demande au moment où vous le faites:

def myview(request): 
    form = VehicleForm(instance=whatever, request=request) 
+1

+1. Publiez le code pour montrer comment vous instanciez le formulaire. –

+0

J'utilise une vue générique, ajoutée ci-dessus. Je devrais donc utiliser une vue personnalisée selon votre exemple? – Dan1ell

+0

Oui, vous allez avoir besoin d'une vue personnalisée ici. –

3

Voici une version plus courte de la façon dont j'écrirais la vue ces jours-ci, juste pour les yeux futurs. Pas besoin __init__ subclassing, et aucune répétition du constructeur du formulaire:

@login_required 
def create_vehicle(request): 
    form = forms.VehicleForm(data=request.POST or None) 
    if form.is_valid(): 
     form.instance.owner = request.user 
     form.save() 
     return redirect('vehicles') 
    return render(request, 'vehicles/vehicle_create.html', {'form': form})