Modelesq
Modelesq

Reputation: 5382

Django object isn't saving username with get_or_create()

I'm trying to save my TagStatus object. Right now it's saving, however its not saving the username, nor is it saving the tag foreign key.

Whats its saving right now is this:

user : __________ (empty) 
status : Status 2 
tag : _________ (empty)

What am I doing wrong? Why isn't the username or tag saving? Thank you for your help in advance.

the model:

class TagStatus(models.Model):
    user = models.ForeignKey(User, null=True, unique=True)
    status = models.CharField(max_length=2, choices=tag_statuses)
    tag = models.ForeignKey(Tag, null=True, blank=True)

    def __unicode__(self):
        return self.status

    def save(self, *args, **kwargs):
        super(TagStatus, self).save(*args, **kwargs)

my view:

@login_required
def tags(request):
    all_tags = Tag.objects.all()
    context = base_context(request)
    if request.method == 'POST':
        if 'status_check' in request.POST:
            status = int(request.POST['select'])
            tag = request.POST['tag']
            user = request.user
            try:
                tag_status = TagStatus.objects.get_or_create(status=status, tag__slug=tag, user__username=user.username)
            except TagStatus.DoesNotExist:
                tag_status = None
            response = simplejson.dumps({"status": "Successfully changed status"})
        else:
            response = simplejson.dumps({"status": "Error"})
            return HttpResponse (response, mimetype='application/json')
    status_form = TagStatusForm()
    context['all_tags'] = all_tags
    return render_to_response('tags/tags.html', context, context_instance=RequestContext(request))

template:

<form class="nice" id="status-form" method="POST" action="">
     {% csrf_token %}
     <input type="hidden" name="status_check" />
     <input type='hidden' name="tag" value="{{ tag.slug }}" />
     <select name="select" id="positionSelect" class="input-text category" onchange="this.form.submit()">
          <option name="all" value="0">Your Status</option>
          <option name="investing" value="1">Status 1</option>
          <option name="selling" value="2">Status 2</option>
          <option name="interested" value="3">Status 3</option>
     </select>
</form>

Upvotes: 0

Views: 1602

Answers (4)

catherine
catherine

Reputation: 22808

I don't know why you use get_or_create in adding new tag. You have to use get_or_create, if you are both doing querying or saving. What I saw in your view is your just adding it, no querying. So why you make it difficult if you can just put it,

new_tag = Tag.object.create(slug=tag)
TagStatus.objects.create(status=status, tag=new_tag, user=user)

That will solve your problem.

@login_required
def tags(request):
    all_tags = Tag.objects.all()
    context = base_context(request)
    if request.method == 'POST':
        if 'status_check' in request.POST:
            status = int(request.POST['select'])
            tag = request.POST['tag']
            user = request.user

            new_tag = Tag.object.create(slug=tag)
            TagStatus.objects.create(status=status, tag=new_tag, user=user)

            response = simplejson.dumps({"status": "Successfully changed status"})
        else:
            response = simplejson.dumps({"status": "Error"})
            return HttpResponse (response, mimetype='application/json')
    status_form = TagStatusForm()
    context['all_tags'] = all_tags
    return render_to_response('tags/tags.html', context, context_instance=RequestContext(request))

Upvotes: 1

user2246087
user2246087

Reputation:

You need to do this: Change:

tag_status = TagStatus.objects.get_or_create(status=status, tag__slug=tag, user__username=user.username)

to:

tag_status, _ = TagStatus.objects.get_or_create(status=status, tag=tag, user=user, defaults={'user': user, 'tag': tag})
tag_status.save()

Also, tag should be of Tag instance, you can do:

tag, _ = Tag.objects.get_or_create(slug=request.POST['tag'])

If slug is a slug_field, you can do slugify(request.POST['tag']) the get_or_create returns 2 parameters - one is the object, the other is the created = True/False to depict if a new object was created

Also, TagStatus.DoesNotExist will never occur since you are using get_or_create

Upvotes: 3

dusual
dusual

Reputation: 2207

Extending from @user2246087 answer just add the following:

tag.slug = request.POST['tag']
tag.save()

and then

tag_status, created = TagStatus.objects.get_or_create(status=status, tag=tag, user=user, defaults={'user': user, 'tag': tag})

You do not need to add the TagStatus.save()

Upvotes: 0

I'm not sure exactly what's wrong with your code, but this is not what you should be doing. Django forms handle all of this stuff for you automatically--the creation of the form, the conversion from post data to python data, and saving the model. They also do lots of validation that is really really helpful that you would never figure out how to do yourself.

Please see the Django form documentation: https://docs.djangoproject.com/en/dev/topics/forms/

Upvotes: 0

Related Questions