Doug Smith
Doug Smith

Reputation: 580

django - view that creates or updates a model but requires a submit

I have class based modelview where I want the model/instance to be created or updated. If updating, I want the fields to show their current values. I have this working except that the instance is being created just by loading the view/template. As soon as the page loads, the object is saved. I think it's very important that the save is not done until the submit button is clicked.

I also want to override the model's save() method because I need to check what field is being updated and update a different model/object.

Model

class GradeBookSetup(DirtyFieldsMixin, models.Model):
    user = models.OneToOneField(CustomUser, on_delete=CASCADE)
    level1 = models.IntegerField(default=55)
    scale_mode = models.CharField(max_length=7, blank=True, default="VSB")
    teacher_show_sec_percent = models.BooleanField(default=True)

    def save(self, *args, **kwargs):
        super(GradeBookSetup, self).save(*args, **kwargs)
        if 'scale_mode' in dirty_fields:
            objs = Grade.objects.filter(user=self.user)
            n = 0
            for grade in objs:
                 objs[n].score = "BEG"

View

@method_decorator([login_required], name='dispatch')
class GradeBookSetupCreateView(UpdateView):
    form_class = GradeBookSetupForm
    model = GradeBookSetup

    success_url = "/gradebook/"

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

    def get_object(self, queryset=None):
        obj, created = GradeBookSetup.objects.get_or_create(
            user=self.request.user)
        return obj

Form

class GradeBookSetupForm(forms.ModelForm):

    class Meta:
        model = GradeBookSetup
        fields = ['level1', 'scale_mode', 'teacher_show_sec_percent']
        labels = {
            "level1": "What percent?",
            "scale_mode": "Choose your proficiency scale.",
            'teacher_show_sec_percent': "Teacher view (10-12), show percent",
        }

EDIT My next try is to move the get_or_create into the form_valid method as suggested by hendrikschneider. I still need to get the object to display the correct values after the initial save so I mean to do this with the try:. I had to change the get_or_create to update_or_create.

def form_valid(self, form):
    form.instance.user = self.request.user
    form.instance, created = GradeBookSetup.objects.update_or_create(
        user=self.request.user, defaults={'scale_mode':form.instance.scale_mode})
    return super().form_valid(form)

def get_object(self, queryset=None):
    try:
        obj = GradeBookSetup.objects.get(user=self.request.user)
        return obj
    except:
        pass

Upvotes: 0

Views: 34

Answers (1)

hendrikschneider
hendrikschneider

Reputation: 1846

The issue is your get_object method. The method is called when a get and when a post request is executed. As you use get_or_create there, it is always executed. Make sure that you only get_or_create in your form_valid method and not in get_object.

Upvotes: 2

Related Questions