简体   繁体   中英

Django User foreign key in View vs in model.save() method

I have the following model (simplified):

class Candidate(models.Model):
    """ Model for candidate clients """

    # fields
    general_category = models.ForeignKey('GeneralCategory',
                                         related_name='candidate',
                                         null=True,
                                         blank=True,
                                         # default=1,
                                         verbose_name='Γενική Κατηγορία',)

    brand_name = models.CharField(max_length=160,
                                  blank=True,
                                  verbose_name='Επωνυμία')

    creation_date = models.DateTimeField(null=True, blank=True, verbose_name='Πρώτη καταχώρηση')
    last_edited = models.DateTimeField(null=True, blank=True, verbose_name='Τελευταία επεξεργασία')

    first_edited_by = models.ForeignKey(User,
                                        related_name='first_edited_candidates',
                                        blank=True,
                                        null=True,
                                        verbose_name='Πρώτη επεξεργασία από',)

    last_edited_by = models.ForeignKey(User,
                                       related_name='last_edited_candidates',
                                       blank=True,
                                       null=True,
                                       verbose_name='Τελευταία επεξεργασία από',)

    def save(self, *args, **kwargs):
        """ On save, update timestamps and user fields """
        if 'request' in kwargs:
            request = kwargs.pop('request')
        else:
            request = None

        if not self.id:
            self.creation_date = timezone.now()
        self.last_edited = timezone.now()

        if request is not None:
            if not self.first_edited_by:
                self.first_edited_by = request.user
            self.last_edited_by = request.user

        log.info(self)
        return super(Candidate, self).save(*args, **kwargs)

    def __str__(self):
        return self.brand_name + '[' + str(self.__dict__) + ']'

If I fire up the debugger in PyCharm I can see that the two User foreign keys are populated as expected in my detail view, but inside the model.save() method they are None . The other foreign key ( general_category ) is populated as expected.

Why is that? Does it have something to do with the self keyword?

My view (again, simplified) is this:

@login_required
@require_http_methods(["GET", "POST"])
def candidate_detail(request, candidate_id):
    candidate = get_object_or_404(Candidate, pk=candidate_id)
    original_http_referrer = request.GET.get('next')
    if request.method == 'GET':
        form = CandidateForm(instance=candidate)
    elif request.method == 'POST':
        form = CandidateForm(request.POST, instance=candidate)
        if form.is_valid():
            candidate.save(request=request)
            return HttpResponseRedirect(original_http_referrer)
        # else:
            # TODO: show some error message ?

    context = {'candidate': candidate,
               'form': form,
               'original_http_referrer': original_http_referrer}
    return render(request, 'candidates/candidate_detail.html', context)

I'm using Django 1.8 with Python 3.4 .

UPDATE: It seems that the value of the foreign keys is lost in the line

form = CandidateForm(request.POST, instance=candidate)

The weird thing is that, if I step-in and go line-by-line with the debugger, my program ends up working as expected! (I have also tried this using manage.py runserver to make sure it is not a bug in the PyCharm's server implementation and it's not)

I'll try logging my model at each step tomorrow to narrow down the offending code. Just to make sure, here is my form's code (not simplified):

from django.forms import ModelForm
from candidates.models import Candidate


class CandidateForm(ModelForm):
    class Meta:
        model = Candidate
        fields = '__all__'

You didn't save the form.

    if form.is_valid():
        candidate = form.save(commit=False)
        candidate.save(request=request)

Note that the first four lines of the save method can be simplified to one:

request = kwargs.pop('request', None)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM