2016-06-26 9 views
5

Huh, aus irgendeinem Grund kann ich nicht scheinen, dass F funktioniert, selbst bei den einfachsten Modellen. Hier auf Django 1.9.x.Django F scheint nicht zu funktionieren?

In der einfachsten Form Testaccount

class TestAccount(models.Model): 
    decimal = models.DecimalField(max_digits=5, decimal_places=2) 
    integer = models.IntegerField() 



In [1]: ta = TestAccount() 

In [2]: ta.integer = 1 

In [3]: ta.decimal = 1 

In [4]: ta.save() 

In [5]: 

In [5]: 

In [5]: ta 
Out[5]: <TestAccount: TestAccount object> 

In [6]: ta.id 
Out[6]: 1L 

In [7]: from django.db.models.expressions import F 

In [8]: ta = TestAccount.objects.get(id=1) 

In [9]: ta.integer = F('integer') + 1 

In [10]: ta.save() 
--------------------------------------------------------------------------- 
ValidationError       Traceback (most recent call last) 
<ipython-input-10-6e9eda341b34> in <module>() 
----> 1 ta.save() 

/usr/lib/python2.7/site-packages/django/db/models/base.pyc in save(self, force_insert, force_update, using, update_fields) 
    706 
    707   self.save_base(using=using, force_insert=force_insert, 
--> 708      force_update=force_update, update_fields=update_fields) 
    709  save.alters_data = True 
    710 

/usr/lib/python2.7/site-packages/django/db/models/base.pyc in save_base(self, raw, force_insert, force_update, using, update_fields) 
    730   if not meta.auto_created: 
    731    signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using, 
--> 732         update_fields=update_fields) 
    733   with transaction.atomic(using=using, savepoint=False): 
    734    if not raw: 

/usr/lib/python2.7/site-packages/django/dispatch/dispatcher.pyc in send(self, sender, **named) 
    190 
    191   for receiver in self._live_receivers(sender): 
--> 192    response = receiver(signal=self, sender=sender, **named) 
    193    responses.append((receiver, response)) 
    194   return responses 

/media/sf_helium/build/helium/internal/signals.pyc in validate_model(sender, **kwargs) 
    12 def validate_model(sender, **kwargs): 
    13  if 'raw' in kwargs and not kwargs['raw']: 
---> 14   kwargs['instance'].full_clean() 
    15 
    16 @receiver(pre_delete) 

/usr/lib/python2.7/site-packages/django/db/models/base.pyc in full_clean(self, exclude, validate_unique) 
    1142 
    1143   if errors: 
-> 1144    raise ValidationError(errors) 
    1145 
    1146  def clean_fields(self, exclude=None): 

ValidationError: {'integer': [u"'F(integer) + Value(1)' value must be an integer."]} 

Aber nach dieser: https://docs.djangoproject.com/en/1.9/ref/models/instances/#updating-attributes-based-on-existing-fields es sollte ... arbeiten

Warum ist F nicht von der Validierung ausgeschlossen werden, weiß ich nicht. Es sollte sein, und Django sollte nur eine Abfrage erstellen, um es zu aktualisieren.

Antwort

5

Dies funktioniert in reinem Django. Das Problem in Ihrem Fall ist, dass Sie einen Zuhörer haben (in helium.internal.signals) an das pre_save Signal, das dies zu tun versucht:

def validate_model(sender, **kwargs): 
    if 'raw' in kwargs and not kwargs['raw']: 
     kwargs['instance'].full_clean() 

Model.full_clean ein paar Werte für jedes Feld in Ihrem Modell erwartet, aber in diesem Fall eines Ihrer Felder ist kein Wert, sondern ein CombinedExpression, der noch nicht ausgewertet wurde, und wird nur ausgewertet, wenn Django in die Datenbank schreibt. Dies verursacht den Fehler.

IMO müssen Sie entweder Ihre eigene Validierung durchgeführt werden, die die Logik von full_clean implementiert und Griffe Expression s, oder Sie müssen Felder ausschließen Ausdrücke aus full_clean enthält.

Verwandte Themen