Ошибка проверки формы Django с неполными полями, но с полным экземпляром - PullRequest
2 голосов
/ 06 октября 2011

Я хочу иметь возможность:

def update_profile(request, username):
    user = Profile.objects.get(user__username=username)

    # update subset of profile, eg value_to_company is set in request.POST
    # but user (or an arbitrary number of other attributes) is not
    profile = ProfileForm(request.POST, instance=user)

    if not profile.is_valid():
        print profile.errors  #user is required

Проблема, с которой я сталкиваюсь, заключается в том, что пользователь определенно существует и является частью экземпляра, и я не могу найти в документах ничего, чтобыпредположить, что данные экземпляра не попадут в связанные данные.Но я также не могу найти ничего, что явно говорит о том, что это будет .

(Остальное это оправдание того, почему я делаю то, что я есть, и идеи для решенийВам, вероятно, не нужно читать это.)

Если вы хотите знать, почему я прохожу форму - не важно для вопроса - это потому, что у меня есть что-то вроде этого:

class Profile(models.Model):
    user = models.ForeignKey(auth.models.User)
    value_to_company = models.IntegerField()

class ValueField(forms.Field):
    def to_python(self, value):
        vals = {'high': 0,
                'mid': 1}
        return vals[value]

class ProfileForm(forms.ModelForm):
    value_to_company = ValueField()

    class Meta:
        model = Profile

То есть я уже выполняю приведение типа api-to-internal-presentation-coercion в своих формах, и я хотел бы продолжить его использование.

Я мог бы переопределитьЦикл forms.is_valid (), просто проверяющий поля в форме, которые уже существуют, что-то хакерское, например:

# replaces `if not profile.is_valid()` above:
errors = []
for field in request.POST.iterkeys():
    if field in profile.fields:
        profile.fields[field].to_python()
        if not profile.fields['field'].clean():
            errors.append #something

(Я на самом деле не смотрел внутреннюю логику логики, поэтому я знаю, что это неправильно, но вы поняли.)

Ответы [ 2 ]

0 голосов
/ 28 ноября 2011

Я нашел это решение в Джанго-поршень .

Он добавляет дополнительный метод формы merge_from_initial, который вы вызываете перед вызовом is_valid, и заполняетпропущенные поля из данного объекта.

Я немного его изменил и использую:

class BaseModelForm(forms.ModelForm):
    """
    Subclass of `forms.ModelForm` which makes sure that the instance values are present in the form
    data, so you don't have to send all old values for the form to actually validate. Django does not
    do this on its own.
    """

    def merge_from_instance(self):
        # Internals
        self.data._mutable = True

        fun = lambda v: v not in self.data.keys()
        for field in filter(fun, self.fields.keys()):
            if field not in self.initial:
                continue
            value = self.initial.get(field)
            if isinstance(self.instance._meta.get_field(field), related.ManyToManyField):
                self.data.setlist(field, value)
            else:
                self.data[field] = value
0 голосов
/ 06 октября 2011

Скорее всего, вам просто нужно добавить exclude = ('user',) к вашей форме.Экземпляр формы в основном определяет начальные значения, если ваша форма содержит поле пользователя, но это поле публикуется с пустым значением, оно будет пытаться очистить поле пользователя, что приведет к ошибке.

...