Domanda

I am a newbie to Django and this question might be an easy one, but it has already been bothering me for a while.

<form method="post" action="/vote/" class="vote_form">
   <input type="hidden" id="id_link" name="user_profile" class="hidden_id" value="5" />
   <input type="hidden" id="id_voter" name="voter" class="hidden_id" value="3" />
    New Score: <input name="score" class="" value="7" />
    <button type="submit">Submit</button>
</form>

urls.py

url(r'^vote/$', auth(VoteFormView.as_view()), name="vote"),

views.py

class VoteFormView(FormView):
    form_class = VoteForm

    def create_response(self, vdict=dict(), valid_form=True):
        response = HttpResponse(json.dumps(vdict))
        response.status = 200 if valid_form else 500
        return response

    def form_valid(self, form):
        profile = get_object_or_404(UserProfile, pk=form.data['user_profile'])
        user = self.request.user
        score = form.cleaned_data['score']

        prev_votes = Vote.objects.filter(voter=user, profile=profile)
        has_voted = (len(prev_votes) > 0)

        ret = {"success": 1, "profile": profile, "voter: ": user}
        if not has_voted:
            # add vote
            v = Vote.objects.create(voter=user, profile=profile, score=score)
            ret["voteobj"] = v.id
            # else response already ranked  
        return self.create_response(ret, True)


    def form_invalid(self, form):
        ...do something when form invalid...

forms.py

class VoteForm(forms.ModelForm):
   class Meta:
     model = Vote

models.py

class Vote(models.Model):
    voter = models.ForeignKey(User)
    profile = models.ForeignKey(UserProfile)
    score = models.FloatField(default=10.0)

    def __unicode__(self):
        return "%s voted %s" % (self.voter.username, self.profile)

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    # Extra attributes

As you can see, I have a simple form with 2 fields: a user_profile (PK of a user profile) and a score. After the form is submitted, it has this error: "form_errors": {"profile": ["This field is required."]} . So it always goes to to form_invalid. Where am I supposed to get profile object if it is not form_valid? I tried to redefine VoteForm as below, which does not work either.

class VoteForm(forms.ModelForm):
    def clean_profile(self):
        profile_pk = self.cleaned_data['profile']
        profile = None
        try:
            profile = UserProfile.objects.get(pk=profile_pk)
        except UserProfile.DoesNotExist:
            raise forms.ValidationError("User profile doesn't exist.")
        return profile

    def save(self, *args, **kwargs):
        vote = super(VoteForm, self).save(*args, **kwargs)
        return vote

    class Meta:
        model = Vote

Any ideas?

È stato utile?

Soluzione

You have to change your hidden input name from user_profile to profile.

Keep in mind this is a poor design since anyone can inject an arbitrary voter id.

Here is how I would do it

class VoteForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop("user")
        super(VoteForm, self).__init__(*args, **kwargs)

    def save(self, *args, **kwargs):

        # manipulate self.user

and then in your view

form = VoteForm(..., user=request.user)

Altri suggerimenti

The name of your hidden field is user_profile, but your code refers to it as just profile. Try changing the html of the form so it is named profile.

As an aside you should include the voter id in your form, that should be added in your processing code based on the logged in user. Currently anyone could change the voter hidden field and record a vote for a different user.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top